home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / net / sun4.md / netUltra.c < prev   
C/C++ Source or Header  |  1992-12-18  |  89KB  |  3,040 lines

  1. /* 
  2.  * netUltra.c --
  3.  *
  4.  *    Routines for handling the Ultranet VME Adapter card..
  5.  *
  6.  * Copyright 1990 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/net/sun4.md/netUltra.c,v 1.7 92/04/14 22:34:08 jhh Exp $ SPRITE (Berkeley)";
  18. #endif /* not lint */
  19.  
  20. #include <sprite.h>
  21. #include <vm.h>
  22. #include <vmMach.h>
  23. #include <mach.h>
  24. #include <netUltraInt.h>
  25. #include <dev/ultra.h>
  26. #include <fmt.h>
  27. #include <sync.h>
  28. #include <dbg.h>
  29. #include <rpcPacket.h>
  30. #include <assert.h>
  31.  
  32. /*
  33.  * "Borrow" the Vax format for the format of the Ultranet adapter (it
  34.  * is really a 386.  We need to swap some of the words in the
  35.  * diagnostic and information structures.
  36.  */
  37.  
  38. #define NET_ULTRA_FORMAT FMT_VAX_FORMAT
  39.  
  40. Boolean        netUltraDebug = FALSE;
  41. Boolean        netUltraTrace = TRUE;
  42. int        netUltraMapThreshold = NET_ULTRA_MAP_THRESHOLD;
  43. static int    packetsSunk = 0;
  44. static Time    sinkStartTime;
  45. static Time    sinkEndTime;
  46.  
  47. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  48.  
  49. #define WAIT_FOR_REPLY(ptr, count) {        \
  50.     int    i;                    \
  51.     for(i = (count); i > 0; i -= 100) {        \
  52.     MACH_DELAY(100);            \
  53.     if (*((volatile int *)ptr) != 0) {    \
  54.         break;                \
  55.     }                    \
  56.     }                        \
  57. }
  58.  
  59. /*
  60.  * The following are the names of the diagnostic tests as listed in the
  61.  * uvm man page provided in the Ultranet documentation.
  62.  */
  63. static char    *diagNames[] = {
  64.     "EPROM checksum",
  65.     "Abbreviated RAM check",
  66.     "Interrupt controller and interval timer",
  67.     "Internal loopback",
  68.     "FIFO RAM check",
  69.     "Checksum gate arrays",
  70.     "NMI control logic"
  71. };
  72. /*
  73.  * The following are the names of the extended diagnostic tests as
  74.  * listed in the uvm man page.
  75.  */
  76. static char    *extDiagNames[] = {
  77.     "EPROM checksum",
  78.     "Full RAM check",
  79.     "Interrupt controller and interval timer",
  80.     "Internal or external loopback",
  81.     "FIFO RAM check",
  82.     "Checksum gate arrays",
  83.     "NMI control logic",
  84.     "DMA to hosts memory using VME bus",
  85.     "Extended FIFO RAM check",
  86.     "FIFO Control logic"
  87. };
  88.  
  89. /*
  90.  * This is a "wildcard" address that matches any TL address.
  91.  * Once again we have to lie about the size of a Net_Address
  92.  * since the adapter will puke if it isn't 7 bytes (why have it
  93.  * if you can't change it?).
  94.  */
  95. static Net_UltraTLAddress    wildcardAddress = 
  96.                 {7, NET_ULTRA_TSAP_SIZE};
  97.  
  98. /*
  99.  * Forward declarations.
  100.  */
  101.  
  102. static Sync_Condition    dsndTestDone;
  103. static int        dsndCount;
  104.  
  105. static char         *GetStatusString _ARGS_ ((int status));
  106. static void        InitQueues _ARGS_((NetUltraState *statePtr));
  107. static void        StandardDone _ARGS_((Net_Interface *interPtr, 
  108.                 NetUltraXRBInfo *infoPtr));
  109. static void        ReadDone _ARGS_((Net_Interface *interPtr, 
  110.                 NetUltraXRBInfo *infoPtr));
  111. static void        EchoDone _ARGS_((Net_Interface *interPtr, 
  112.                 NetUltraXRBInfo *infoPtr));
  113. static ReturnStatus    NetUltraSendDgram _ARGS_((Net_Interface *interPtr,
  114.                 Net_Address *netAddressPtr, int count,
  115.                 int bufSize, Address buffer, Time *timePtr));
  116. static void        DgramSendDone _ARGS_((Net_Interface *interPtr, 
  117.                 NetUltraXRBInfo *infoPtr));
  118. static void        OutputDone _ARGS_((Net_Interface *interPtr, 
  119.                 NetUltraXRBInfo *infoPtr));
  120. static void        SourceDone _ARGS_((Net_Interface *interPtr, 
  121.                 NetUltraXRBInfo *infoPtr));
  122. static ReturnStatus    NetUltraSource _ARGS_((Net_Interface *interPtr,
  123.                 Net_Address *netAddressPtr, int count,
  124.                 int bufSize, Address buffer, Time *timePtr));
  125. static void        NetUltraResetCallback _ARGS_((ClientData data,
  126.                 Proc_CallInfo *infoPtr));
  127.  
  128. /*
  129.  * Macros for mapping between kernel, DVMA and VME addresses.
  130.  */
  131.  
  132. #define    DVMA_TO_BUFFER(addr, statePtr)         \
  133.     ((Address) (((((unsigned int) (addr)) -     \
  134.     ((unsigned int) (statePtr)->buffersDVMA)) + \
  135.     ((int) (statePtr)->buffers))))
  136.  
  137. #define BUFFER_TO_DVMA(addr, statePtr)         \
  138.     ((Address) ((((unsigned int) (addr)) -     \
  139.     ((unsigned int) (statePtr)->buffers)) +     \
  140.     ((unsigned int) (statePtr)->buffersDVMA)))
  141.  
  142. #define DVMA_TO_VME(addr, statePtr)         \
  143.     ((Address) (((unsigned int) (addr)) -     \
  144.     ((unsigned int) VMMACH_DMA_START_ADDR)))
  145.  
  146. #define VME_TO_DVMA(addr, statePtr)         \
  147.     ((Address) (((unsigned int) (addr)) +     \
  148.     ((unsigned int) VMMACH_DMA_START_ADDR)))
  149.  
  150. #define BUFFER_TO_VME(addr, statePtr) \
  151.     ((Address) (DVMA_TO_VME(BUFFER_TO_DVMA(addr,statePtr), (statePtr))))
  152.  
  153. #define VME_TO_BUFFER(addr, statePtr) \
  154.     ((Address) (DVMA_TO_BUFFER(VME_TO_DVMA((addr),statePtr),(statePtr))))
  155.  
  156. #define DVMA_ADDRESS(addr, statePtr) \
  157.     ((unsigned int) (addr) < ((unsigned int)VMMACH_DMA_START_ADDR)? FALSE :TRUE)
  158.  
  159.  
  160.  
  161. /*
  162.  *----------------------------------------------------------------------
  163.  *
  164.  * NetUltraInit --
  165.  *
  166.  *    Initialize the Ultranet VME adapter card.
  167.  *
  168.  * Results:
  169.  *    SUCCESS if the Ultranet card was found and initialized.
  170.  *    FAILURE otherwise.
  171.  *
  172.  * Side effects:
  173.  *    None.
  174.  *
  175.  *----------------------------------------------------------------------
  176.  */
  177.  
  178. ReturnStatus
  179. NetUltraInit(interPtr)
  180.     Net_Interface    *interPtr;     /* Network interface. */
  181. {
  182.     unsigned int        ctrlAddr;
  183.     NetUltraState        *statePtr;
  184.     ReturnStatus        status = SUCCESS;
  185.     int                zero = 0;
  186.     NetUltraExtDiagCommand     extDiagCmd;
  187.     NetUltraInfoCommand        infoCmd;
  188.     char            *buffer;
  189.  
  190.     /*
  191.      * Make sure that we agree with the adapter as to the size of the 
  192.      * command blocks and other structures.
  193.      */
  194.     assert(sizeof(Net_UltraAddress) == 8);
  195.     assert(sizeof(Net_UltraTLAddress) == 16);
  196.     assert(sizeof(Net_UltraHeader) == 56);
  197.     assert(sizeof(NetUltraDMAInfo) == 16);
  198.     assert(sizeof(NetUltraRequestHdr) == 16);
  199.     assert(sizeof(NetUltraDatagramRequest) == 56);
  200.     assert(sizeof(NetUltraStartRequest) == 112);
  201.     assert(sizeof(NetUltraStopRequest) == 16);
  202.     assert(sizeof(NetUltraRequest) == 112);
  203.     assert(sizeof(NetUltraXRB) == 132);
  204.     assert(sizeof(NetUltraInitCommand) == 64);
  205.     assert(sizeof(NetUltraDiagCommand) == 36);
  206.     assert(sizeof(NetUltraExtDiagCommand) == 24);
  207.     assert(sizeof(NetUltraLoadCommand) == 24);
  208.     assert(sizeof(NetUltraGoCommand) == 12);
  209.     assert(sizeof(Net_UltraHeader) == sizeof(NetUltraDatagramRequest));
  210.  
  211.     ctrlAddr = (unsigned int) interPtr->ctrlAddr;
  212.     /*
  213.      * If the address is physical (not in kernel's virtual address space)
  214.      * then we have to map it in.
  215.      */
  216.     if (interPtr->virtual == FALSE) {
  217.     ctrlAddr = (unsigned int) VmMach_MapInDevice((Address) ctrlAddr, 3);
  218.     }
  219.     statePtr = (NetUltraState *) malloc (sizeof(NetUltraState));
  220.     bzero((char *) statePtr, sizeof(NetUltraState));
  221.     /*
  222.      * The first register is the interrupt register, then
  223.      * the reset register, separated by 12 bytes.
  224.      */
  225.     statePtr->intrReg = (int *) ctrlAddr;
  226.     statePtr->resetReg = (int *) (ctrlAddr + 0x10);
  227.     /*
  228.      * Now poke the reset register.
  229.      */
  230.     status = Mach_Probe(sizeof(int), (char *) &zero,
  231.         (char *) statePtr->resetReg);
  232.     if (status != SUCCESS) {
  233.     /* 
  234.      * Got a bus error.
  235.      */
  236.     goto exit;
  237.     }
  238.     if (netUltraDebug) {
  239.     printf("NetUltraInit: adapter at 0x%x probed successfully\n",
  240.         statePtr->intrReg);
  241.     }
  242.     MACH_DELAY(NET_ULTRA_RESET_DELAY);
  243.     statePtr->magic = NET_ULTRA_STATE_MAGIC;
  244.     statePtr->flags = NET_ULTRA_STATE_EXIST | NET_ULTRA_STATE_EPROM |
  245.             NET_ULTRA_STATE_NORMAL;
  246.     statePtr->interPtr = interPtr;
  247.     interPtr->interfaceData = (ClientData) statePtr;
  248.     statePtr->tracePtr = statePtr->traceBuffer;
  249.     statePtr->traceSequence = 0;
  250.     /*
  251.      * Get the adapter information.
  252.      */
  253.     status = NetUltraInfo(statePtr, &infoCmd);
  254.     if (status == SUCCESS) {
  255.     printf(
  256.     "UltraNet adapter %d.%d, Revision %d, Option %d, Firmware %d, Serial %d\n",
  257.         infoCmd.hwModel, infoCmd.hwVersion, 
  258.         infoCmd.hwRevision, infoCmd.hwOption,
  259.         infoCmd.version, infoCmd.hwSerial);
  260.     if (infoCmd.error == 0) {
  261.         printf("Ultranet adapter passed all diagnostics.\n");
  262.     } else {
  263.         int    tmp = infoCmd.error;
  264.         int i;
  265.         printf(
  266.         "Ultranet adapter failed diagnostics (0x%x).\n", tmp);
  267.         printf("The following tests failed:\n");
  268.         for (i = 0; i < sizeof(int) * 8; i++) {
  269.         if (tmp & 1) {
  270.             printf("%2d: %s\n", i+1, diagNames[i]);
  271.         }
  272.         tmp >>= 1;
  273.         }
  274.         status = FAILURE;
  275.         goto exit;
  276.     }
  277.     } else {
  278.     printf("NetUltraInit: unable to send info command to adapter\n");
  279.     goto exit;
  280.     }
  281.     /*
  282.      * Send an extended diagnostics command to the adapter.
  283.      */
  284.     buffer = (char *) malloc(NET_ULTRA_EXT_DIAG_BUF_SIZE);
  285.     status = NetUltraExtDiag(statePtr, FALSE, buffer, &extDiagCmd);
  286.     free(buffer);
  287.     if (status == SUCCESS) {
  288.     if (extDiagCmd.error == 0) {
  289.         printf("Ultranet adapter passed all extended diagnostics.\n");
  290.     } else {
  291.         int    tmp = extDiagCmd.error;
  292.         int i;
  293.         printf(
  294.         "Ultranet adapter failed extended diagnostics (0x%x).\n", tmp);
  295.         printf("The following tests failed:\n");
  296.         for (i = 0; i < sizeof(int) * 8; i++) {
  297.         if (tmp & 1) {
  298.             printf("%2d: %s\n", i+1, extDiagNames[i]);
  299.         }
  300.         tmp >>= 1;
  301.         }
  302.         status = FAILURE;
  303.         goto exit;
  304.     } 
  305.     } else {
  306.     printf(
  307.     "NetUltraInit: unable to send extended diagnostics command to adapter\n");
  308.     goto exit;
  309.     }
  310.     interPtr->ctrlAddr = (Address) ctrlAddr;
  311.     statePtr->queuesInit = FALSE;
  312.     InitQueues(statePtr);
  313.     statePtr->priority = NET_ULTRA_INTERRUPT_PRIORITY;
  314.     statePtr->requestLevel = NET_ULTRA_VME_REQUEST_LEVEL;
  315.     statePtr->addressSpace = NET_ULTRA_VME_ADDRESS_SPACE;
  316.     Mach_SetHandler(interPtr->vector, Net_Intr, (ClientData) interPtr);
  317.     interPtr->init     = NetUltraInit;
  318.     interPtr->intr    = NetUltraIntr;
  319.     interPtr->ioctl    = NetUltraIOControl;
  320.     interPtr->reset     = Net_UltraReset;
  321.     interPtr->output     = NetUltraOutput;
  322.     interPtr->netType    = NET_NETWORK_ULTRA;
  323.     interPtr->maxBytes    = NET_ULTRA_MAX_BYTES;
  324.     interPtr->minBytes    = NET_ULTRA_MIN_BYTES;
  325.     if (sizeof(NetUltraXRB) != 132) {
  326.     printf("NetUltraInit: WARNING: NetUltraXRB is not 132 bytes!!!\n");
  327.     }
  328. exit:
  329.     if (status != SUCCESS && statePtr != (NetUltraState *) NIL) {
  330.     free((char *) statePtr);
  331.     }
  332.     return status;
  333. }
  334.  
  335. /*
  336.  *----------------------------------------------------------------------
  337.  *
  338.  * NetUltraHardReset --
  339.  *
  340.  *    Does a hard reset of the Ultranet adapter. This means the adapter
  341.  *    board goes back to its state right after power-up -- no 
  342.  *    micro-code or anything.
  343.  *
  344.  * Results:
  345.  *    SUCCESS if a reply was received properly, FAILURE otherwise
  346.  *
  347.  * Side effects:
  348.  *    The ultranet adapter is initialized.
  349.  *
  350.  *----------------------------------------------------------------------
  351.  */
  352.  
  353. ReturnStatus
  354. NetUltraHardReset(interPtr)
  355.     Net_Interface    *interPtr;    /* Interface to reset. */
  356. {
  357.     NetUltraState    *statePtr;    /* State of the adapter. */
  358.     ReturnStatus    status = SUCCESS;
  359.     int            zero = 0;
  360.  
  361.     statePtr = (NetUltraState *) interPtr->interfaceData;
  362.     printf("Ultra: adapter reset.\n");
  363.     status = Mach_Probe(sizeof(int), (char *) &zero, 
  364.         (char *) statePtr->resetReg);
  365.     if (status != SUCCESS) {
  366.     /*
  367.      * Adapter is no longer responding.
  368.      */
  369.     printf("NetUltraHardReset: adapter did not respond to reset!!\n");
  370.     statePtr->flags = 0;
  371.     return FAILURE;
  372.     }
  373.     MACH_DELAY(NET_ULTRA_RESET_DELAY);
  374.     InitQueues(statePtr);
  375.     /*
  376.      * After a reset the adapter is in the EPROM mode.
  377.      * This allows several additional commands (load, go, etc.) to be
  378.      * sent to the adapter.
  379.      */
  380.     statePtr->flags = NET_ULTRA_STATE_EXIST | NET_ULTRA_STATE_EPROM;
  381.     return status;
  382. }
  383.  
  384. /*
  385.  *----------------------------------------------------------------------
  386.  *
  387.  * NetUltraInitAdapter --
  388.  *
  389.  *    Allocate the various queues and send the initialization command
  390.  *    to the adapter.
  391.  *
  392.  * Results:
  393.  *    Standard Sprite return status.
  394.  *
  395.  * Side effects:
  396.  *    The adapter board is initialized.
  397.  *
  398.  *----------------------------------------------------------------------
  399.  */
  400.  
  401. ReturnStatus
  402. NetUltraInitAdapter(statePtr)
  403.     NetUltraState    *statePtr;    /* State of the adapter. */
  404. {
  405.     ReturnStatus    status;
  406.     NetUltraInitCommand    cmd;        /* Init command block. */
  407.     Net_Interface    *interPtr;
  408.  
  409.     interPtr = statePtr->interPtr;
  410.     MASTER_LOCK(&interPtr->mutex);
  411.     if (!(statePtr->flags & NET_ULTRA_STATE_GO)) {
  412.     if (netUltraDebug) {
  413.         printf("NetUltraInitAdapter: device is not started.\n");
  414.     }
  415.     status = FAILURE;
  416.     goto exit;
  417.     }
  418.     bzero((char *) &cmd, sizeof(cmd));
  419.     cmd.opcode = NET_ULTRA_INIT_OPCODE;
  420.     cmd.toAdapterAddr = (int) DVMA_TO_VME(statePtr->firstToAdapterPtr, 
  421.                     statePtr);
  422.     cmd.toAdapterNum = statePtr->lastToAdapterPtr - 
  423.             statePtr->firstToAdapterPtr + 1;
  424.     cmd.toHostAddr = (int) DVMA_TO_VME(statePtr->firstToHostPtr, statePtr);
  425.     cmd.toHostNum = statePtr->lastToHostPtr - statePtr->firstToHostPtr + 1;
  426.     cmd.XRBSize = sizeof(NetUltraXRB);
  427.     cmd.priority = (char) statePtr->priority;
  428.     cmd.vector = (char) interPtr->vector;
  429.     cmd.requestLevel = (char) statePtr->requestLevel;
  430.     cmd.addressSpace = (char) statePtr->addressSpace;
  431.     status = NetUltraSendCmd(statePtr, NET_ULTRA_INIT_OK, sizeof(cmd), 
  432.             (Address) &cmd);
  433.     if (status != SUCCESS) {
  434.     if (cmd.reply == NET_ULTRA_BAD_SIZE) {
  435.         printf("NetUltraInitAdapter: adapter disagrees on size of XRB\n");
  436.     }
  437.     goto exit;
  438.     }
  439.     statePtr->flags &= ~NET_ULTRA_STATE_GO;
  440.     statePtr->flags |= NET_ULTRA_STATE_INIT;
  441. exit:
  442.     MASTER_UNLOCK(&interPtr->mutex);
  443.     return status;
  444.  
  445. /*
  446.  *----------------------------------------------------------------------
  447.  *
  448.  * NetUltraStart--
  449.  *
  450.  *    Send a start request to the board.
  451.  *    Assumes the interface mutex is held.
  452.  *
  453.  * Results:
  454.  *    Standard Sprite return status.
  455.  *
  456.  * Side effects:
  457.  *    A start request is sent to the board.
  458.  *
  459.  *----------------------------------------------------------------------
  460.  */
  461.  
  462. ReturnStatus
  463. NetUltraStart(statePtr)
  464.     NetUltraState    *statePtr;    /* State of the adapter. */
  465. {
  466.     NetUltraRequest        request;
  467.     NetUltraStartRequest    *startPtr;
  468.     NetUltraRequestHdr        *hdrPtr;
  469.     Net_Interface        *interPtr;
  470.     int                i;
  471.     int                power = 0;
  472.     int                tmp;
  473.     ReturnStatus        status = SUCCESS;
  474.     static int            sequence = 0;
  475.     Sync_Condition        startComplete;
  476.  
  477.     interPtr = statePtr->interPtr;
  478.     startPtr = &request.start;
  479.     hdrPtr = &startPtr->hdr;
  480.     if (Net_AddrCmp(&interPtr->netAddress[NET_PROTO_RAW],
  481.         &netZeroAddress)){
  482.     printf(
  483. "NetUltraStart: can't send start command - adapter address not set\n");
  484.     status = FAILURE;
  485.     goto exit;
  486.     }
  487.     if (statePtr->flags & NET_ULTRA_STATE_START) {
  488.     printf("NetUltraStart: adapter already started.\n");
  489.     status = FAILURE;
  490.     goto exit;
  491.     }
  492.     if (!(statePtr->flags & NET_ULTRA_STATE_INIT)) {
  493.     printf("NetUltraStart: adapter not initialized.\n");
  494.     status = FAILURE;
  495.     goto exit;
  496.     }
  497.     bzero((char *) &request, sizeof(request));
  498.     hdrPtr->cmd = NET_ULTRA_NEW_START_REQ;
  499.     startPtr->sequence = sequence;
  500.     sequence++;
  501.     startPtr->hostType = NET_ULTRA_START_HOSTTYPE_SUN;
  502.     /*
  503.      * Determine which power of 2 equals the maximum packet size. 
  504.      */
  505.     tmp = interPtr->maxBytes;
  506.     for (i = 0; i < sizeof(int) * 8; i++) {
  507.     if (tmp & 1) {
  508.         power = i;
  509.     }
  510.     tmp >>= 1;
  511.     }
  512.     if (1 << power > interPtr->maxBytes) {
  513.     power++;
  514.     }
  515.     startPtr->hostMaxBytes = power;
  516.     /* 
  517.      * This part is kind of goofy.  The adapter expects the network
  518.      * address to be 7 bytes long (the first byte is missing). We have
  519.      * to bcopy the netAddress minus its first byte.
  520.      */
  521.     startPtr->netAddressSize = 7;
  522.     bcopy(&(((char *) &interPtr->netAddress[NET_PROTO_RAW])[1]),
  523.     (char *) &startPtr->netAddressBuf, sizeof(Net_UltraAddress)-1);
  524.     startPtr->netAddressBuf[0] = 0x49;
  525.     startPtr->netAddressBuf[5] = 0xfe;
  526.     status = NetUltraSendReq(statePtr, StandardDone, 
  527.         (ClientData) &startComplete, FALSE, 
  528.         0, (Net_ScatterGather *) NIL, sizeof(NetUltraStartRequest), 
  529.         &request);
  530.     if (status != SUCCESS) {
  531.     printf("NetUltraStart: unable to send start request\n");
  532.     goto exit;
  533.     }
  534.     Sync_MasterWait(&(startComplete), &(interPtr->mutex), FALSE);
  535.     if (hdrPtr->status & NET_ULTRA_STATUS_OK) {
  536.     if (netUltraDebug) {
  537.         printf("NetUltraStart: hdrPtr->status = %d : %s\n",
  538.         hdrPtr->status, GetStatusString(hdrPtr->status));
  539.     }
  540.     if (netUltraDebug) {
  541.         printf("Ultranet adapter started\n");
  542.         printf("Ucode %d\n", startPtr->ucodeRel);
  543.         printf("Adapter type %d, adapter hw %d\n", startPtr->adapterType,
  544.         startPtr->adapterHW);
  545.         printf("Max VC = %d\n", startPtr->maxVC);
  546.         printf("Max DRCV = %d\n", startPtr->maxDRCV);
  547.         printf("Max DSND = %d\n", startPtr->maxDSND);
  548.         printf("Slot = %d\n", startPtr->slot);
  549.         printf("Speed = %d\n", startPtr->speed);
  550.         printf("Max bytes = %d\n", startPtr->adapterMaxBytes);
  551.     }
  552.     if (startPtr->maxDRCV < statePtr->maxReadPending) {
  553.         printf("NetUltraStart: WARNING: max pending reads reset to %d\n",
  554.         startPtr->maxDRCV);
  555.         statePtr->maxReadPending = startPtr->maxDRCV;
  556.     }
  557.     if (startPtr->maxDSND < statePtr->maxWritePending) {
  558.         printf("NetUltraStart: WARNING: max pending writes reset to %d\n",
  559.         startPtr->maxDSND);
  560.         statePtr->maxWritePending = startPtr->maxDSND;
  561.     }
  562.     if (startPtr->adapterMaxBytes < power) {
  563.         interPtr->maxBytes = 1 << power;
  564.         printf("NetUltraStart: WARNING: max bytes reset to %d\n",
  565.         interPtr->maxBytes);
  566.     }
  567.     statePtr->flags = (NET_ULTRA_STATE_EXIST | NET_ULTRA_STATE_START |
  568.                 NET_ULTRA_STATE_NORMAL);
  569.     /*
  570.      * Now queue up pending reads. 
  571.      */
  572.     for (i = 0; i < statePtr->maxReadPending; i++) {
  573.         List_Links        *itemPtr;
  574.         Address    buffer;
  575.         itemPtr = List_First(statePtr->freeBufferList);
  576.         if (itemPtr == statePtr->freeBufferList) {
  577.         panic("NetUltraOutput: list screwup\n");
  578.         }
  579.         List_Remove(itemPtr);
  580.         buffer = BUFFER_TO_DVMA(itemPtr, statePtr);
  581.         status = NetUltraPendingRead(interPtr, statePtr->bufferSize,
  582.             buffer);
  583.         if (status != SUCCESS) {
  584.         printf("NetUltraStart: could not queue pending read.\n");
  585.         }
  586.     }
  587.     } else {
  588.     printf("NetUltraStart: start command failed <0x%x> : %s\n",
  589.         hdrPtr->status, GetStatusString(hdrPtr->status));
  590.     }
  591. exit:
  592.     return status;
  593. }
  594.  
  595. /*
  596.  *----------------------------------------------------------------------
  597.  *
  598.  * StandardDone --
  599.  *
  600.  *    This is a callback routine that is called from the interrupt
  601.  *    handler when "standard" commands complete. It copies the request
  602.  *    from the XRB in the queue to the request structure pointed
  603.  *    to by the XRB.  This allows the XRB to be used again.
  604.  *    If the data field in the info structure is not NIL then it
  605.  *    is assumed to be a pointer to a condition variable and a
  606.  *    broadcast is done on that variable.
  607.  *
  608.  *
  609.  * Results:
  610.  *    None.
  611.  *
  612.  * Side effects:
  613.  *    None.
  614.  *    
  615.  *
  616.  *----------------------------------------------------------------------
  617.  */
  618.  
  619. /* ARGSUSED */
  620. static void
  621. StandardDone(interPtr, infoPtr)
  622.     Net_Interface    *interPtr;    /* Interface. */
  623.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  624. {
  625.     bcopy((char *) &infoPtr->xrbPtr->request, (char *) infoPtr->requestPtr,
  626.     infoPtr->requestSize);
  627.     if (infoPtr->doneData != (ClientData) NIL) {
  628.     Sync_Broadcast((Sync_Condition *) infoPtr->doneData);
  629.     }
  630. }
  631.  
  632. /*
  633.  *----------------------------------------------------------------------
  634.  *
  635.  * NetUltraStop--
  636.  *
  637.  *    Send a stop request to the board.
  638.  *    Assumes the interface mutex is held.
  639.  *
  640.  * Results:
  641.  *    Standard Sprite return status.
  642.  *
  643.  * Side effects:
  644.  *    The adapter abandons what it is doing.
  645.  *
  646.  *----------------------------------------------------------------------
  647.  */
  648.  
  649. ReturnStatus
  650. NetUltraStop(statePtr)
  651.     NetUltraState    *statePtr;    /* State of the adapter. */
  652. {
  653.     NetUltraRequest        request;
  654.     NetUltraStopRequest        *stopPtr;
  655.     NetUltraRequestHdr        *hdrPtr;
  656.     Net_Interface        *interPtr;
  657.     ReturnStatus        status = SUCCESS;
  658.     Sync_Condition        stopComplete;
  659.  
  660.     interPtr = statePtr->interPtr;
  661.     stopPtr = &request.stop;
  662.     hdrPtr = &stopPtr->hdr;
  663.     if (!(statePtr->flags & NET_ULTRA_STATE_START)) {
  664.     printf("NetUltraStop: adapter not started.\n");
  665.     status = FAILURE;
  666.     goto exit;
  667.     }
  668.     bzero((char *) &request, sizeof(request));
  669.     hdrPtr->cmd = NET_ULTRA_STOP_REQ;
  670.     status = NetUltraSendReq(statePtr, StandardDone, 
  671.         (ClientData) &stopComplete, FALSE,
  672.         0, (Net_ScatterGather *) NIL, sizeof(NetUltraStopRequest), 
  673.         &request);
  674.     if (status != SUCCESS) {
  675.     printf("NetUltraStop: unable to send stop request\n");
  676.     goto exit;
  677.     }
  678.     Sync_MasterWait(&(stopComplete), &(interPtr->mutex), FALSE);
  679.     if (hdrPtr->status & NET_ULTRA_STATUS_OK) {
  680.     if (netUltraDebug) {
  681.         printf("NetUltraStop: hdrPtr->status = %d : %s\n",
  682.         hdrPtr->status, GetStatusString(hdrPtr->status));
  683.     }
  684.     statePtr->flags &= ~NET_ULTRA_STATE_START;
  685.     } else {
  686.     printf("NetUltraStop: stop command failed <0x%x> : %s\n",
  687.         hdrPtr->status, GetStatusString(hdrPtr->status));
  688.     }
  689. exit:
  690.     return status;
  691. }
  692.  
  693. /*
  694.  *----------------------------------------------------------------------
  695.  *
  696.  * NetUltraReset --
  697.  *
  698.  *    Resets the board by sending it a stop command followed by a
  699.  *    start command.  The XRB queues are also initialized.
  700.  *    Assumes the interface mutex is held.
  701.  *
  702.  * Results:
  703.  *    A standard Sprite return status.
  704.  *
  705.  * Side effects:
  706.  *    None.
  707.  *
  708.  *----------------------------------------------------------------------
  709.  */
  710.  
  711. ReturnStatus
  712. NetUltraReset(interPtr)
  713.     Net_Interface    *interPtr;    /* Interface to reset. */
  714. {
  715.     ReturnStatus    status = SUCCESS;
  716.     NetUltraState    *statePtr;    /* State of the adapter. */
  717.  
  718.     statePtr = (NetUltraState *) interPtr->interfaceData;
  719.     status = NetUltraStop(statePtr);
  720.     if (status != NULL) {
  721.     printf("NetUltraReset: stop failed\n");
  722.     return status;
  723.     }
  724.     InitQueues(statePtr);
  725.     status = NetUltraStart(statePtr);
  726.     if (status != NULL) {
  727.     printf("NetUltraReset: start failed\n");
  728.     return status;
  729.     }
  730.     return status;
  731. }
  732.  
  733. /*
  734.  *----------------------------------------------------------------------
  735.  *
  736.  * Net_UltraReset --
  737.  *
  738.  *    This is a version of the reset routine that can be called
  739.  *     from outside the module since it locks the mutex.
  740.  *
  741.  * Results:
  742.  *    
  743.  *
  744.  * Side effects:
  745.  *    None.
  746.  *
  747.  *----------------------------------------------------------------------
  748.  */
  749.  
  750. void
  751. Net_UltraReset(interPtr)
  752.     Net_Interface    *interPtr;    /* Interface to reset. */
  753. {
  754.     MASTER_LOCK(&interPtr->mutex);
  755.     /*
  756.      * If we are at interrupt level we have to do a callback to reset
  757.      * the adapter since we can't wait for the response from
  758.      * the adapter (there may not be a current process and we can't
  759.      * get the interrupt).
  760.      */
  761.     if (Mach_AtInterruptLevel()) {
  762.     Proc_CallFunc(NetUltraResetCallback, (ClientData) interPtr, 0);
  763.     } else {
  764.     (void) NetUltraReset(interPtr);
  765.     }
  766.     MASTER_UNLOCK(&interPtr->mutex);
  767. }
  768.  
  769. /*
  770.  *----------------------------------------------------------------------
  771.  *
  772.  * NetUltraResetCallback --
  773.  *
  774.  *    This routine is called by the Proc_ServerProc during the
  775.  *    callback to reset the adapter.
  776.  *
  777.  * Results:
  778.  *    None.
  779.  *
  780.  * Side effects:
  781.  *    The adapter is reset.
  782.  *
  783.  *----------------------------------------------------------------------
  784.  */
  785. /*ARGSUSED*/
  786. static void
  787. NetUltraResetCallback(data, infoPtr)
  788.     ClientData        data;        /* Ptr to the interface to reset. */
  789.     Proc_CallInfo    *infoPtr;    /* Unused. */
  790. {
  791.     Net_UltraReset((Net_Interface *) data);
  792. }
  793.  
  794.  
  795. /*
  796.  *----------------------------------------------------------------------
  797.  *
  798.  * Net_UltraHardReset --
  799.  *
  800.  *    This is a version of the hard reset routine that can be called from
  801.  *     outside the net module because it does not assume that a
  802.  *    lock is held (or interrupts are disabled) when it is called.
  803.  *
  804.  * Results:
  805.  *    None.
  806.  *
  807.  * Side effects:
  808.  *    The adapter is reset.
  809.  *
  810.  *----------------------------------------------------------------------
  811.  */
  812.  
  813. void
  814. Net_UltraHardReset(interPtr)
  815.     Net_Interface    *interPtr;    /* Interface to reset. */
  816. {
  817.     MASTER_LOCK(&interPtr->mutex);
  818.  
  819.     NetUltraHardReset(interPtr);
  820.  
  821.     MASTER_UNLOCK(&interPtr->mutex);
  822. }
  823.  
  824.  
  825. /*
  826.  *----------------------------------------------------------------------
  827.  *
  828.  * NetUltraDiag --
  829.  *
  830.  *    Send a diagnostic command to the adapter.
  831.  *
  832.  * Results:
  833.  *    SUCCESS if the adapter processed the command correctly,
  834.  *    FAILURE otherwise.
  835.  *
  836.  * Side effects:
  837.  *    The adapter is sent a diagnostic command.
  838.  *
  839.  *----------------------------------------------------------------------
  840.  */
  841.  
  842. ReturnStatus
  843. NetUltraDiag(statePtr, cmdPtr)
  844.     NetUltraState    *statePtr;    /* State of the adapter. */
  845.     NetUltraDiagCommand    *cmdPtr;    /* Diagnostic command block. */
  846. {
  847.     ReturnStatus        status = SUCCESS;
  848.     NetUltraDiagCommand        tmpCmd;    
  849.     int                inSize;
  850.     int                outSize;
  851.     int                fmtStatus;
  852.  
  853.     MASTER_LOCK(&statePtr->interPtr->mutex);
  854.     if (!(statePtr->flags & NET_ULTRA_STATE_EPROM)) {
  855.     if (netUltraDebug) {
  856.         printf("NetUltraDiag: device is not in EPROM state.\n");
  857.     }
  858.     status = FAILURE;
  859.     goto exit;
  860.     }
  861.     if (netUltraDebug) {
  862.     printf("Sending diagnostic command to adapter.\n");
  863.     }
  864.     bzero((char *) &tmpCmd, sizeof(tmpCmd));
  865.     tmpCmd.opcode = NET_ULTRA_DIAG_OPCODE;
  866.     status = NetUltraSendCmd(statePtr, NET_ULTRA_DIAG_OK, 
  867.             sizeof(tmpCmd), (Address) &tmpCmd);
  868.     if (status != SUCCESS) {
  869.     goto exit;
  870.     }
  871.     cmdPtr->reply = tmpCmd.reply;
  872.     cmdPtr->version = tmpCmd.version;
  873.     cmdPtr->error = tmpCmd.error;
  874.     /*
  875.      * The hardware related fields are returned in Intel 386 byte-order.
  876.      */
  877.     inSize = 5 * sizeof(int);
  878.     outSize = inSize;
  879.     fmtStatus = Fmt_Convert("w5", NET_ULTRA_FORMAT, &inSize, 
  880.             (char *) &(tmpCmd.hwModel), mach_Format, &outSize, 
  881.             (char *) &(cmdPtr->hwModel));
  882.     if (fmtStatus != 0) {
  883.     printf("NetUltraInfo: Format returned %d\n");
  884.     status = FAILURE;
  885.     goto exit;
  886.     }
  887. exit:
  888.     MASTER_UNLOCK(&statePtr->interPtr->mutex)
  889.     return status;
  890. }
  891.  
  892. /*
  893.  *----------------------------------------------------------------------
  894.  *
  895.  * NetUltraInfo --
  896.  *
  897.  *    Send an info command to the adapter. The results are the same
  898.  *     as the diagnostic command, except the diagnostics are not 
  899.  *    actually run.  Presumably we are fetching the results of the
  900.  *    last time diagnostics were run, probably due to a reset.
  901.  *
  902.  * Results:
  903.  *    SUCCESS if the adapter processed the command correctly,
  904.  *    FAILURE otherwise.
  905.  *
  906.  * Side effects:
  907.  *    The adapter is sent an info command.
  908.  *
  909.  *----------------------------------------------------------------------
  910.  */
  911.  
  912. ReturnStatus
  913. NetUltraInfo(statePtr, cmdPtr)
  914.     NetUltraState    *statePtr;    /* State of the adapter. */
  915.     NetUltraInfoCommand    *cmdPtr;    /* Info command block. */
  916. {
  917.     ReturnStatus        status = SUCCESS;
  918.     int                fmtStatus;
  919.     NetUltraInfoCommand        tmpCmd;
  920.     int                inSize;
  921.     int                outSize;
  922.  
  923.     MASTER_LOCK(&statePtr->interPtr->mutex);
  924.     if (!(statePtr->flags & NET_ULTRA_STATE_EPROM)) {
  925.     if (netUltraDebug) {
  926.         printf("NetUltraInfo: device is not in EPROM state.\n");
  927.     }
  928.     status = FAILURE;
  929.     goto exit;
  930.     }
  931.     if (netUltraDebug) {
  932.     printf("Sending Info command to adapter.\n");
  933.     }
  934.     bzero((char *) &tmpCmd, sizeof(NetUltraInfoCommand));
  935.     tmpCmd.opcode = NET_ULTRA_INFO_OPCODE;
  936.     status = NetUltraSendCmd(statePtr, NET_ULTRA_INFO_OK, 
  937.             sizeof(NetUltraInfoCommand), (Address) &tmpCmd);
  938.     if (status != SUCCESS) {
  939.     goto exit;
  940.     }
  941.     cmdPtr->reply = tmpCmd.reply;
  942.     cmdPtr->version = tmpCmd.version;
  943.     cmdPtr->error = tmpCmd.error;
  944.     /*
  945.      * The hardware related fields are returned in Intel 386 byte-order.
  946.      */
  947.     inSize = 5 * sizeof(int);
  948.     outSize = inSize;
  949.     fmtStatus = Fmt_Convert("w5", NET_ULTRA_FORMAT, &inSize, 
  950.             (char *) &(tmpCmd.hwModel), mach_Format, &outSize, 
  951.             (char *) &(cmdPtr->hwModel));
  952.     if (fmtStatus != 0) {
  953.     printf("NetUltraInfo: Format returned %d\n");
  954.     status = FAILURE;
  955.     }
  956. exit:
  957.     MASTER_UNLOCK(&statePtr->interPtr->mutex)
  958.     return status;
  959. }
  960.  
  961. /*
  962.  *----------------------------------------------------------------------
  963.  *
  964.  * NetUltraExtDiag --
  965.  *
  966.  *    Send an extended diagnostic command to the adapter.
  967.  *
  968.  * Results:
  969.  *    SUCCESS if the adapter processed the command correctly,
  970.  *    FAILURE otherwise.
  971.  *
  972.  * Side effects:
  973.  *    The adapter is sent an extended diagnostic command.
  974.  *
  975.  *----------------------------------------------------------------------
  976.  */
  977.  
  978. ReturnStatus
  979. NetUltraExtDiag(statePtr, external, buffer, cmdPtr)
  980.     NetUltraState    *statePtr;    /* State of the adapter. */
  981.     Boolean        external;    /* TRUE => use external loopback
  982.                      * adapter. */
  983.     char        buffer[];     /* Used for VME tests. */
  984.     NetUltraExtDiagCommand    *cmdPtr;    /* Extended diagnostic command
  985.                          * block. */
  986. {
  987.     ReturnStatus        status = SUCCESS;
  988.     Address            bufAddress;
  989.  
  990.     MASTER_LOCK(&statePtr->interPtr->mutex);
  991.     if (!(statePtr->flags & NET_ULTRA_STATE_EPROM)) {
  992.     if (netUltraDebug) {
  993.         printf("NetUltraExtDiag: device is not in EPROM state.\n");
  994.     }
  995.     status = FAILURE;
  996.     goto exit;
  997.     }
  998.     if (netUltraDebug) {
  999.     printf("Sending extended diagnostic command to adapter.\n");
  1000.     }
  1001.     bufAddress = (Address) VmMach_DMAAlloc(NET_ULTRA_EXT_DIAG_BUF_SIZE, buffer);
  1002.     if (bufAddress == (Address) NIL) {
  1003.     printf("NetUltraExtDiag: unable to allocate buffer in DMA space.\n");
  1004.     status = FAILURE;
  1005.     }
  1006.     bzero((char *) cmdPtr, sizeof(*cmdPtr));
  1007.     cmdPtr->opcode = NET_ULTRA_EXT_DIAG_OPCODE;
  1008.     cmdPtr->externalLoopback = (external == TRUE) ? 1 : 0;
  1009.     cmdPtr->bufferAddress = (int) DVMA_TO_VME(bufAddress, statePtr);
  1010.     status = NetUltraSendCmd(statePtr, NET_ULTRA_EXT_DIAG_OK, sizeof(*cmdPtr), 
  1011.         (Address) cmdPtr);
  1012.     VmMach_DMAFree(NET_ULTRA_EXT_DIAG_BUF_SIZE, bufAddress);
  1013. exit:
  1014.     MASTER_UNLOCK(&statePtr->interPtr->mutex);
  1015.     return status;
  1016. }
  1017.  
  1018. /*
  1019.  *----------------------------------------------------------------------
  1020.  *
  1021.  * NetUltraLoad --
  1022.  *
  1023.  *    Download a block of ucode onto the adapter.
  1024.  *
  1025.  * Results:
  1026.  *    SUCCESS if the command was processed properly
  1027.  *
  1028.  * Side effects:
  1029.  *    Data is loaded into the adapter ram.
  1030.  *
  1031.  *----------------------------------------------------------------------
  1032.  */
  1033.  
  1034. ReturnStatus
  1035. NetUltraLoad(statePtr, address, length, ucodePtr)
  1036.     NetUltraState    *statePtr;    /* State of the adapter. */
  1037.     int            address;    /* Load address of ucode. */
  1038.     int            length;        /* Size of ucode. */
  1039.     Address        ucodePtr;    /* Ucode buffer. */
  1040. {
  1041.     NetUltraLoadCommand        cmd;
  1042.     int                inSize;
  1043.     int                outSize;
  1044.     int                fmtStatus;
  1045.     Address            dmaAddress;
  1046.     ReturnStatus        status = SUCCESS;
  1047.  
  1048.     MASTER_LOCK(&statePtr->interPtr->mutex);
  1049.     if (!(statePtr->flags & NET_ULTRA_STATE_EPROM)) {
  1050.     if (netUltraDebug) {
  1051.         printf("NetUltraExtDiag: device is not in EPROM state.\n");
  1052.     }
  1053.     status = FAILURE;
  1054.     goto exit;
  1055.     }
  1056.     if (netUltraDebug) {
  1057.     printf("Sending load command to adapter.\n");
  1058.     printf("Address = 0x%x, length = %d\n", address, length);
  1059.     }
  1060.     /*
  1061.      * Convert the address and length to Intel format.
  1062.      */
  1063.     inSize = sizeof(int);
  1064.     outSize = sizeof(int);
  1065.     fmtStatus = Fmt_Convert("w", mach_Format, &inSize,
  1066.             (char *) &address, NET_ULTRA_FORMAT, &outSize,
  1067.             (char *) &(cmd.loadAddress));
  1068.     if (fmtStatus != 0) {
  1069.     printf("NetUltraLoad: Fmt_Convert returned %d\n",
  1070.         fmtStatus);
  1071.     status = FAILURE;
  1072.     goto exit;
  1073.     }
  1074.     inSize = sizeof(int);
  1075.     outSize = sizeof(int);
  1076.     fmtStatus = Fmt_Convert("w", mach_Format, &inSize,
  1077.             (char *) &length, NET_ULTRA_FORMAT, &outSize,
  1078.             (char *) &(cmd.length));
  1079.     if (fmtStatus != 0) {
  1080.     printf("NetUltraLoad: Fmt_Convert returned %d\n",
  1081.         fmtStatus);
  1082.     status = FAILURE;
  1083.     goto exit;
  1084.     }
  1085.     cmd.opcode = NET_ULTRA_LOAD_OPCODE;
  1086.     cmd.reply = 0;
  1087.     /*
  1088.      * Map the ucode into DVMA space.
  1089.      */
  1090.     dmaAddress = (Address) VmMach_DMAAlloc(length, ucodePtr); 
  1091.     cmd.dataAddress = (unsigned long) DVMA_TO_VME(dmaAddress, statePtr);
  1092.     status = NetUltraSendCmd(statePtr, NET_ULTRA_LOAD_OK, sizeof(cmd), 
  1093.         (Address) &cmd);
  1094.     VmMach_DMAFree(length, dmaAddress);
  1095.     if (status != SUCCESS) {
  1096.     goto exit;
  1097.     }
  1098.     statePtr->flags |= NET_ULTRA_STATE_LOAD;
  1099. exit:
  1100.     MASTER_UNLOCK(&statePtr->interPtr->mutex)
  1101.     return status;
  1102. }
  1103.  
  1104. /*
  1105.  *----------------------------------------------------------------------
  1106.  *
  1107.  * NetUltraGo --
  1108.  *
  1109.  *    Send the go command to the adapter to start its processor
  1110.  *    running the ucode.
  1111.  *
  1112.  * Results:
  1113.  *    SUCCESS if it worked, FAILURE otherwise
  1114.  *
  1115.  * Side effects:
  1116.  *    The adapter cpu begins executing.
  1117.  *
  1118.  *----------------------------------------------------------------------
  1119.  */
  1120.  
  1121. ReturnStatus
  1122. NetUltraGo(statePtr, address)
  1123.     NetUltraState    *statePtr;    /* State of the adapter. */
  1124.     int            address;    /* Start address. */
  1125. {
  1126.     NetUltraGoCommand        cmd;
  1127.     int                inSize;
  1128.     int                outSize;
  1129.     int                fmtStatus;
  1130.     ReturnStatus        status = SUCCESS;
  1131.  
  1132.     MASTER_LOCK(&statePtr->interPtr->mutex);
  1133.     if (!(statePtr->flags & NET_ULTRA_STATE_EPROM)) {
  1134.     if (netUltraDebug) {
  1135.         printf("NetUltraExtDiag: device is not in EPROM state.\n");
  1136.     }
  1137.     status = FAILURE;
  1138.     goto exit;
  1139.     }
  1140.     if (!(statePtr->flags & NET_ULTRA_STATE_LOAD)) {
  1141.     if (netUltraDebug) {
  1142.         printf("NetUltraGo: ucode not downloaded.\n");
  1143.     }
  1144.     status = FAILURE;
  1145.     goto exit;
  1146.     }
  1147.     if (netUltraDebug) {
  1148.     printf("Sending go command to adapter.\n");
  1149.     }
  1150.     /*
  1151.      * Convert the address into Intel format.
  1152.      */
  1153.     inSize = sizeof(int);
  1154.     outSize = sizeof(int);
  1155.     fmtStatus = Fmt_Convert("w", mach_Format, &inSize,
  1156.             (char *) &address, NET_ULTRA_FORMAT, &outSize,
  1157.             (char *) &(cmd.startAddress));
  1158.     if (fmtStatus != 0) {
  1159.     printf("NetUltraGo: Fmt_Convert returned %d\n",
  1160.         fmtStatus);
  1161.     status = FAILURE;
  1162.     goto exit;
  1163.     }
  1164.     cmd.opcode = NET_ULTRA_GO_OPCODE;
  1165.     cmd.reply = 0;
  1166.     status = NetUltraSendCmd(statePtr, NET_ULTRA_GO_OK, sizeof(cmd), 
  1167.         (Address) &cmd);
  1168.     if (status != SUCCESS) {
  1169.     goto exit;
  1170.     }
  1171.     statePtr->flags &= ~NET_ULTRA_STATE_LOAD;
  1172.     statePtr->flags |= NET_ULTRA_STATE_GO;
  1173.     statePtr->flags &= ~NET_ULTRA_STATE_EPROM;
  1174. exit:
  1175.     MASTER_UNLOCK(&statePtr->interPtr->mutex)
  1176.     return status;
  1177. }
  1178.  
  1179.  
  1180. /*
  1181.  *----------------------------------------------------------------------
  1182.  *
  1183.  * NetUltraSendCmd --
  1184.  *
  1185.  *    Send a command to the adapter.
  1186.  *
  1187.  * Results:
  1188.  *    SUCCESS if the adapter responded to the command,
  1189.  *    DEV_TIMEOUT if the adapter did not respond
  1190.  *
  1191.  * Side effects:
  1192.  *    A command is sent to the adapter.
  1193.  *
  1194.  *----------------------------------------------------------------------
  1195.  */
  1196.  
  1197. ReturnStatus
  1198. NetUltraSendCmd(statePtr, ok,size, cmdPtr)
  1199.     NetUltraState    *statePtr;    /* State of the adapter. */
  1200.     int            ok;        /* Value of reply field if command
  1201.                      * was successful. */
  1202.     int            size;        /* Size of command block. */
  1203.     Address        cmdPtr;        /* The command block. */
  1204. {
  1205.     struct StdCmd {
  1206.     volatile int        opcode;
  1207.     volatile int        reply;
  1208.     } *stdCmdPtr;
  1209.     ReturnStatus    status = SUCCESS;
  1210.  
  1211.     stdCmdPtr = (struct StdCmd *) cmdPtr;
  1212.     if (netUltraDebug) {
  1213.     printf("NetUltraSendCmd: sending command %d to adapter\n",
  1214.         stdCmdPtr->opcode);
  1215.     printf("NetUltraSendCmd: cmdPtr = 0x%x\n", cmdPtr);
  1216.     }
  1217.     if ((int) cmdPtr & 0x3) {
  1218.     panic("NetUltraSendCmd: command not aligned on a word boundary\n");
  1219.     }
  1220.     stdCmdPtr->reply = 0;
  1221.     cmdPtr = VmMach_DMAAlloc(size, cmdPtr);
  1222.     if (cmdPtr == (Address) NIL) {
  1223.     panic("NetUltraSendCmd: can't allocate DMA space for command\n");
  1224.     }
  1225.     if (netUltraDebug) {
  1226.     printf("NetUltraSendCmd: cmdPtr mapped into DMA space\n");
  1227.     printf("NetUltraSendCmd: cmdPtr = 0x%x\n", cmdPtr);
  1228.     }
  1229.     *statePtr->intrReg = 
  1230.     (int) DVMA_TO_VME(cmdPtr,statePtr);
  1231.     WAIT_FOR_REPLY(&stdCmdPtr->reply, NET_ULTRA_DELAY);
  1232.     VmMach_DMAFree(size, cmdPtr);
  1233.     if (stdCmdPtr->reply == 0) {
  1234.     printf("NetUltraSendCmd: adapter timed out\n");
  1235.     status = DEV_TIMEOUT;
  1236.     } else if (stdCmdPtr->reply == ok) {
  1237.     status = SUCCESS;
  1238.     } else {
  1239.     printf("NetUltraSendCmd: adapter returned %d\n", stdCmdPtr->reply);
  1240.     status = FAILURE;
  1241.     }
  1242.     return status;
  1243. }
  1244.  
  1245. /*
  1246.  *----------------------------------------------------------------------
  1247.  *
  1248.  * NetUltraIntr --
  1249.  *
  1250.  *    Handle an interrupt from the Ultranet adapter.
  1251.  *
  1252.  * Results:
  1253.  *    None.
  1254.  *
  1255.  * Side effects:
  1256.  *    None.
  1257.  *
  1258.  *----------------------------------------------------------------------
  1259.  */
  1260.  
  1261. /*ARGSUSED*/
  1262. void
  1263. NetUltraIntr(interPtr, polling)
  1264.     Net_Interface    *interPtr;    /* Interface to process. */
  1265.     Boolean        polling;    /* TRUE if are being polled instead of
  1266.                      * processing an interrupt. */
  1267. {
  1268.     NetUltraXRB        *xrbPtr;
  1269.     NetUltraXRB        *nextXRBPtr;
  1270.     NetUltraState    *statePtr;
  1271.     NetUltraDMAInfo    *dmaPtr;
  1272.     NetUltraRequestHdr  *hdrPtr;
  1273.     NetUltraXRBInfo    *infoPtr;
  1274.     int            processed;
  1275.     NetUltraTraceInfo    *tracePtr;
  1276.     Address        buffer;
  1277.  
  1278.     MASTER_LOCK(&interPtr->mutex);
  1279. #ifndef CLEAN
  1280.     if (netUltraDebug) {
  1281.     printf("Received an Ultranet interrupt.\n");
  1282.     }
  1283. #endif
  1284.     statePtr = (NetUltraState *) interPtr->interfaceData;
  1285.     xrbPtr = statePtr->nextToHostPtr;
  1286. #ifndef CLEAN
  1287.     if (netUltraTrace) {
  1288.     NEXT_TRACE(statePtr, &tracePtr);
  1289.     tracePtr->event = INTERRUPT;
  1290.     Timer_GetCurrentTicks(&tracePtr->ticks);
  1291.     }
  1292. #endif
  1293.     processed = 0;
  1294.     while(xrbPtr->filled != 0) {
  1295.     /*
  1296.      * Compute the next xrb to the host.
  1297.      */
  1298.     if (xrbPtr == statePtr->lastToHostPtr) {
  1299.         nextXRBPtr = statePtr->firstToHostPtr;
  1300.     } else {
  1301.         nextXRBPtr = xrbPtr + 1;
  1302.     }
  1303.     statePtr->nextToHostPtr = nextXRBPtr;
  1304.     dmaPtr = &xrbPtr->dma;
  1305.     if (!(dmaPtr->cmd & NET_ULTRA_DMA_CMD_FROM_ADAPTER)) {
  1306.         printf("NetUltraIntr: cmd (0x%x) not from adapter?\n", dmaPtr->cmd);
  1307.         goto endLoop;
  1308.     }
  1309.     if ((dmaPtr->cmd & NET_ULTRA_DMA_CMD_MASK) != NET_ULTRA_DMA_CMD_XRB) {
  1310.         printf("NetUltraIntr: dmaPtr->cmd = 0x%x\n", dmaPtr->cmd);
  1311.         goto endLoop;
  1312.     }
  1313.     hdrPtr = (NetUltraRequestHdr *) &xrbPtr->request;
  1314.     infoPtr = hdrPtr->infoPtr;
  1315.     if (infoPtr->flags & NET_ULTRA_INFO_PENDING) {
  1316. #ifndef CLEAN
  1317.         if (netUltraDebug) {
  1318.         printf("NetUltraIntr: processing 0x%x\n", infoPtr);
  1319.         }
  1320.         if (netUltraTrace) {
  1321.         NEXT_TRACE(statePtr, &tracePtr);
  1322.         tracePtr->event = PROCESS_XRB;
  1323.         tracePtr->index = xrbPtr - statePtr->firstToHostPtr;
  1324.         tracePtr->infoPtr = infoPtr;
  1325.         Timer_GetCurrentTicks(&tracePtr->ticks);
  1326.         }
  1327. #endif
  1328.         infoPtr->xrbPtr = xrbPtr;
  1329.         if (statePtr->flags & NET_ULTRA_STATE_STATS) {
  1330.         if (hdrPtr->cmd == NET_ULTRA_DGRAM_RECV_REQ) {
  1331.             statePtr->stats.packetsReceived++;
  1332.             statePtr->stats.bytesReceived += hdrPtr->size;
  1333.             statePtr->stats.receivedHistogram[hdrPtr->size >> 10]++;
  1334.         }
  1335.         }
  1336.         /*
  1337.          * Mark the info as not pending.
  1338.          * Clearing the pending bit ensures
  1339.          * that this packet does not get processed twice, since the
  1340.          * master lock around the interface will get released before
  1341.          * calling the RPC system, so that the RPC system can
  1342.          * output a packet. Do not
  1343.          * clear the filled bit since we are using the contents of
  1344.          * the xrb and we don't want the adapter to overwrite it
  1345.          * yet. 
  1346.          */
  1347.         infoPtr->flags &= ~NET_ULTRA_INFO_PENDING;
  1348.         if (infoPtr->doneProc != NILPROC) {
  1349.         (infoPtr->doneProc)(interPtr, infoPtr);
  1350.         }
  1351.         if (infoPtr->flags & NET_ULTRA_INFO_STD_BUFFER) {
  1352.         if (infoPtr->flags & NET_ULTRA_INFO_REMAP) {
  1353.             VmMach_DMAFree(hdrPtr->size, 
  1354.             VME_TO_DVMA(hdrPtr->buffer, statePtr));
  1355.             buffer = infoPtr->buffer;
  1356.         } else {
  1357.             buffer = VME_TO_BUFFER(hdrPtr->buffer, statePtr);
  1358.         }
  1359.         List_InitElement((List_Links *) buffer);
  1360.         List_Insert((List_Links *) buffer,
  1361.                LIST_ATREAR(statePtr->freeBufferList));
  1362.         }
  1363.         List_Remove((List_Links *) infoPtr);
  1364.         List_Insert((List_Links *) infoPtr, 
  1365.         LIST_ATREAR(statePtr->freeXRBInfoList));
  1366.         processed++;
  1367.     } else {
  1368. #ifndef CLEAN
  1369.         if (netUltraTrace) {
  1370.         NEXT_TRACE(statePtr, &tracePtr);
  1371.         tracePtr->event = INFO_NOT_PENDING;
  1372.         tracePtr->index = xrbPtr - statePtr->firstToHostPtr;
  1373.         tracePtr->infoPtr = infoPtr;
  1374.         }
  1375. #endif
  1376.     }
  1377. endLoop: 
  1378.     xrbPtr->filled = 0;
  1379.     xrbPtr = nextXRBPtr;
  1380.     /*
  1381.      * Check and see if there is a free xrb in the "to adapter"
  1382.      * queue.  Presumably the appearance of one in the "to host"
  1383.      * queue implies one freed up in the "to adapter" queue.
  1384.      */
  1385.     if ((statePtr->nextToAdapterPtr->filled != 0) && 
  1386.         (statePtr->toAdapterAvail.waiting == TRUE)) {
  1387.         Sync_Broadcast(&statePtr->toAdapterAvail);
  1388.     }
  1389.     }
  1390. #ifndef CLEAN
  1391.     if (processed == 0) {
  1392.     if (netUltraDebug) {
  1393.         printf("NetUltraIntr: didn't process any packets.\n");
  1394.     }
  1395.     }
  1396. #endif
  1397.     MASTER_UNLOCK(&interPtr->mutex);
  1398. }
  1399.  
  1400. /*
  1401.  *----------------------------------------------------------------------
  1402.  *
  1403.  * NetUltraIOControl --
  1404.  *
  1405.  *    Handle ioctls for the Ultranet adapter..
  1406.  *
  1407.  * Results:
  1408.  *    SUCCESS if the ioctl was performed successfully, a standard
  1409.  *    Sprite error code otherwise.
  1410.  *
  1411.  * Side effects:
  1412.  *    Commands may be sent to the adapter and the adapter state
  1413.  *    may change.
  1414.  *
  1415.  *----------------------------------------------------------------------
  1416.  */
  1417.  
  1418. /*ARGSUSED*/
  1419. ReturnStatus
  1420. NetUltraIOControl(interPtr, ioctlPtr, replyPtr)
  1421.     Net_Interface *interPtr;    /* Interface on which to perform ioctl. */
  1422.     Fs_IOCParam *ioctlPtr;    /* Standard I/O Control parameter block */
  1423.     Fs_IOReply *replyPtr;    /* Size of outBuffer and returned signal */
  1424. {
  1425.     ReturnStatus status = SUCCESS;
  1426.     int    fmtStatus;
  1427.     int inSize;
  1428.     int outSize;
  1429.     NetUltraState    *statePtr = (NetUltraState *) interPtr->interfaceData;
  1430.  
  1431.     if (netUltraDebug) {
  1432.     printf("NetUltraIOControl: command = %d\n", ioctlPtr->command);
  1433.     }
  1434.     if ((ioctlPtr->command & ~0xffff) != IOC_ULTRA) {
  1435.     return DEV_INVALID_ARG;
  1436.     }
  1437.     switch(ioctlPtr->command) {
  1438.     case IOC_ULTRA_SET_FLAGS:
  1439.     case IOC_ULTRA_RESET_FLAGS:
  1440.     case IOC_ULTRA_GET_FLAGS:
  1441.         return GEN_NOT_IMPLEMENTED;
  1442.         break;
  1443.     case IOC_ULTRA_CLR:
  1444.     case IOC_ULTRA_INT:
  1445.     case IOC_ULTRA_WFI:
  1446.         return DEV_INVALID_ARG;
  1447.         break;
  1448.     case IOC_ULTRA_DUMP:
  1449.         return GEN_NOT_IMPLEMENTED;
  1450.         break;
  1451.     case IOC_ULTRA_DEBUG: {
  1452.         int    value;
  1453.         outSize = sizeof(int);
  1454.         inSize = ioctlPtr->inBufSize;
  1455.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1456.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1457.                 (Address) &value);
  1458.         if (fmtStatus != 0) {
  1459.         printf("Format of IOC_ULTRA_DEBUG parameter failed, 0x%x\n",
  1460.             fmtStatus);
  1461.         return GEN_INVALID_ARG;
  1462.         }
  1463.         netUltraDebug = value;
  1464.         break;
  1465.     }
  1466.     case IOC_ULTRA_TRACE: {
  1467.         int    value;
  1468.         outSize = sizeof(int);
  1469.         inSize = ioctlPtr->inBufSize;
  1470.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1471.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1472.                 (Address) &value);
  1473.         if (fmtStatus != 0) {
  1474.         printf("Format of IOC_ULTRA_TRACE parameter failed, 0x%x\n",
  1475.             fmtStatus);
  1476.         return GEN_INVALID_ARG;
  1477.         }
  1478.         netUltraTrace = value;
  1479.         break;
  1480.     }
  1481.     case IOC_ULTRA_RESET: 
  1482.         Net_UltraReset(interPtr);
  1483.         break;
  1484.     case IOC_ULTRA_HARD_RESET:
  1485.         Net_UltraHardReset(interPtr);
  1486.         break;
  1487.     case IOC_ULTRA_GET_ADAP_INFO: {
  1488.         NetUltraInfoCommand        cmd;
  1489.         Dev_UltraAdapterInfo    info;
  1490.  
  1491.         status = NetUltraInfo(statePtr, &cmd);
  1492.         if (status != SUCCESS) {
  1493.         return status;
  1494.         }
  1495.         info.version = cmd.version;
  1496.         info.error = cmd.error;
  1497.         info.hwModel = cmd.hwModel;
  1498.         info.hwVersion = cmd.hwVersion;
  1499.         info.hwRevision = cmd.hwRevision;
  1500.         info.hwOption = cmd.hwOption;
  1501.         info.hwSerial = cmd.hwSerial;
  1502.         inSize = sizeof(info);
  1503.         outSize = ioctlPtr->outBufSize;
  1504.         fmtStatus = Fmt_Convert("{w7}", mach_Format, &inSize,
  1505.         (Address) &info, ioctlPtr->format, &outSize,
  1506.         (Address) ioctlPtr->outBuffer);
  1507.         if (fmtStatus != 0) {
  1508.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  1509.             return GEN_INVALID_ARG;
  1510.         } else {
  1511.             printf(
  1512.             "NetUltraIOControl: Fmt_Convert returned %d\n",
  1513.             fmtStatus);
  1514.             return FAILURE;
  1515.         }
  1516.         }
  1517.         break;
  1518.     }
  1519.     case IOC_ULTRA_DIAG: {
  1520.         NetUltraDiagCommand        cmd;
  1521.         Dev_UltraDiag        diag;
  1522.  
  1523.         status = NetUltraDiag(statePtr, &cmd);
  1524.         if (status != SUCCESS) {
  1525.         return status;
  1526.         }
  1527.         diag.version = cmd.version;
  1528.         diag.error = cmd.error;
  1529.         diag.hwModel = cmd.hwModel;
  1530.         diag.hwVersion = cmd.hwVersion;
  1531.         diag.hwRevision = cmd.hwRevision;
  1532.         diag.hwOption = cmd.hwOption;
  1533.         diag.hwSerial = cmd.hwSerial;
  1534.         inSize = sizeof(diag);
  1535.         outSize = ioctlPtr->outBufSize;
  1536.         fmtStatus = Fmt_Convert("{w7}", mach_Format, &inSize,
  1537.         (Address) &diag, ioctlPtr->format, &outSize,
  1538.         (Address) ioctlPtr->outBuffer);
  1539.         if (fmtStatus != 0) {
  1540.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  1541.             return GEN_INVALID_ARG;
  1542.         } else {
  1543.             printf(
  1544.             "NetUltraIOControl: Fmt_Convert returned %d\n",
  1545.             fmtStatus);
  1546.             return FAILURE;
  1547.         }
  1548.         }
  1549.         break;
  1550.     }
  1551.     case IOC_ULTRA_EXTENDED_DIAG: {
  1552.         NetUltraExtDiagCommand    cmd;
  1553.         Dev_UltraExtendedDiag    extDiag;
  1554.         char            *buffer;
  1555.  
  1556.         buffer = (char *) malloc(NET_ULTRA_EXT_DIAG_BUF_SIZE);
  1557.         inSize = ioctlPtr->inBufSize;
  1558.         outSize = sizeof(extDiag);
  1559.         fmtStatus = Fmt_Convert("{w3}", ioctlPtr->format, &inSize,
  1560.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1561.                 (Address) &extDiag);
  1562.         if (fmtStatus != 0) {
  1563.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1564.             return GEN_INVALID_ARG;
  1565.         } else {
  1566.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1567.             fmtStatus);
  1568.             return FAILURE;
  1569.         }
  1570.         }
  1571.         status = NetUltraExtDiag(statePtr, extDiag.externalLoopback, 
  1572.                 buffer,&cmd);
  1573.         free(buffer);
  1574.         if (status != SUCCESS) {
  1575.         return status;
  1576.         }
  1577.         extDiag.version = cmd.version;
  1578.         extDiag.error = cmd.error;
  1579.         inSize = sizeof(extDiag);
  1580.         outSize = ioctlPtr->outBufSize;
  1581.         fmtStatus = Fmt_Convert("{w3}", mach_Format, &inSize,
  1582.         (Address) &extDiag, ioctlPtr->format, &outSize,
  1583.         (Address) ioctlPtr->outBuffer);
  1584.         if (fmtStatus != 0) {
  1585.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  1586.             return GEN_INVALID_ARG;
  1587.         } else {
  1588.             printf(
  1589.             "NetUltraIOControl: Fmt_Convert returned %d\n",
  1590.             fmtStatus);
  1591.             return FAILURE;
  1592.         }
  1593.         }
  1594.         break;
  1595.     }
  1596.     case IOC_ULTRA_LOAD: {
  1597.         Dev_UltraLoad        load;
  1598.         Address            ucodePtr;
  1599.         inSize = 2 * sizeof(int);
  1600.         outSize = sizeof(load);
  1601.         fmtStatus = Fmt_Convert("w2", ioctlPtr->format, &inSize,
  1602.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1603.                 (Address) &load);
  1604.         if (fmtStatus != 0) {
  1605.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1606.             return GEN_INVALID_ARG;
  1607.         } else {
  1608.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1609.             fmtStatus);
  1610.             return FAILURE;
  1611.         }
  1612.         }
  1613.         /*
  1614.          * This assumes that there isn't any padding between the
  1615.          * two integers in NetUltraLoadCommand and the data buffer.
  1616.          */
  1617.         ucodePtr = (Address) ioctlPtr->inBuffer + inSize;
  1618.         status = NetUltraLoad(statePtr, load.address, load.length,
  1619.                 ucodePtr);
  1620.         break;
  1621.     }
  1622.     case IOC_ULTRA_GO: {
  1623.         Dev_UltraGo            go;
  1624.         inSize = ioctlPtr->inBufSize;
  1625.         outSize = sizeof(go);
  1626.         fmtStatus = Fmt_Convert("{w1}", ioctlPtr->format, &inSize,
  1627.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1628.                 (Address) &go.address);
  1629.         if (fmtStatus != 0) {
  1630.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1631.             return GEN_INVALID_ARG;
  1632.         } else {
  1633.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1634.             fmtStatus);
  1635.             return FAILURE;
  1636.         }
  1637.         }
  1638.         status = NetUltraGo(statePtr, go.address);
  1639.         break;
  1640.     }
  1641.     case IOC_ULTRA_INIT: {
  1642.         status = NetUltraInitAdapter(statePtr);
  1643.         break;
  1644.     }
  1645.     case IOC_ULTRA_START: {
  1646.         MASTER_LOCK(&interPtr->mutex);
  1647.         status = NetUltraStart(statePtr);
  1648.         MASTER_UNLOCK(&interPtr->mutex);
  1649.         break;
  1650.     }
  1651.     case IOC_ULTRA_ADDRESS: {
  1652.         /* 
  1653.          * Set the adapter address.  This is not the normal way to
  1654.          * do this (usually happens during route installation) but
  1655.          * it is useful for debugging. 
  1656.          */
  1657.         Net_UltraAddress    address;
  1658.         int            group;
  1659.         int            unit;
  1660.         inSize = ioctlPtr->inBufSize;
  1661.         outSize = sizeof(Net_UltraAddress);
  1662.         fmtStatus = Fmt_Convert("{b8}", ioctlPtr->format, &inSize,
  1663.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1664.                 (Address) &address);
  1665.         if (fmtStatus != 0) {
  1666.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1667.             return GEN_INVALID_ARG;
  1668.         } else {
  1669.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1670.             fmtStatus);
  1671.             return FAILURE;
  1672.         }
  1673.         }
  1674.         Net_UltraAddressGet(&address, &group, &unit);
  1675.         printf("Setting ultra address to %d/%d\n", group, unit); 
  1676.         MASTER_LOCK(&interPtr->mutex);
  1677.         status = Net_SetAddress(NET_ADDRESS_ULTRA,
  1678.             (Address) &address, 
  1679.             &interPtr->netAddress[NET_PROTO_RAW]);
  1680.         if (status != SUCCESS) {
  1681.         panic("NetUltraIOControl: Net_SetAddress failed\n");
  1682.         }
  1683.         MASTER_UNLOCK(&interPtr->mutex);
  1684.         break;
  1685.     }
  1686.     case IOC_ULTRA_SEND_DGRAM: {
  1687.         Dev_UltraSendDgram        dgram;
  1688.         inSize = ioctlPtr->inBufSize;
  1689.         outSize = sizeof(dgram);
  1690.         fmtStatus = Fmt_Convert("{w2{w2}wb*}", ioctlPtr->format, &inSize,
  1691.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1692.                 (Address) &dgram);
  1693.         if (fmtStatus != 0) {
  1694.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1695.             return GEN_INVALID_ARG;
  1696.         } else {
  1697.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1698.             fmtStatus);
  1699.             return FAILURE;
  1700.         }
  1701.         }
  1702.         status = NetUltraSendDgram(interPtr, &dgram.address, dgram.count,
  1703.             dgram.size, 
  1704.             (dgram.useBuffer == TRUE) ? (Address) dgram.buffer :
  1705.             (Address) NIL, &dgram.time);
  1706.         inSize = sizeof(dgram);
  1707.         outSize = ioctlPtr->outBufSize;
  1708.         fmtStatus = Fmt_Convert("{w2{w2}wb*}", mach_Format, &inSize,
  1709.         (Address) &dgram, ioctlPtr->format, &outSize,
  1710.         (Address) ioctlPtr->outBuffer);
  1711.         if (fmtStatus != 0) {
  1712.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  1713.             return GEN_INVALID_ARG;
  1714.         } else {
  1715.             printf(
  1716.             "NetUltraIOControl: Fmt_Convert returned %d\n",
  1717.             fmtStatus);
  1718.             return FAILURE;
  1719.         }
  1720.         }
  1721.         break;
  1722.     }
  1723.     case IOC_ULTRA_ECHO: {
  1724.         Dev_UltraEcho        echo;
  1725.         inSize = ioctlPtr->inBufSize;
  1726.         outSize = sizeof(echo);
  1727.         fmtStatus = Fmt_Convert("{w}", ioctlPtr->format, &inSize,
  1728.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1729.                 (Address) &echo);
  1730.         if (fmtStatus != 0) {
  1731.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1732.             return GEN_INVALID_ARG;
  1733.         } else {
  1734.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1735.             fmtStatus);
  1736.             return FAILURE;
  1737.         }
  1738.         }
  1739.         if (echo.echo == TRUE) {
  1740.         statePtr->flags |= NET_ULTRA_STATE_ECHO;
  1741.         statePtr->flags &= ~NET_ULTRA_STATE_NORMAL;
  1742.         } else {
  1743.         statePtr->flags &= ~NET_ULTRA_STATE_ECHO;
  1744.         statePtr->flags |= NET_ULTRA_STATE_NORMAL;
  1745.         }
  1746.         break;
  1747.     }
  1748.     case IOC_ULTRA_SOURCE: {
  1749.         Dev_UltraSendDgram        dgram;
  1750.         inSize = ioctlPtr->inBufSize;
  1751.         outSize = sizeof(dgram);
  1752.         fmtStatus = Fmt_Convert("{w2{w2}wb*}", ioctlPtr->format, &inSize,
  1753.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1754.                 (Address) &dgram);
  1755.         if (fmtStatus != 0) {
  1756.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1757.             return GEN_INVALID_ARG;
  1758.         } else {
  1759.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1760.             fmtStatus);
  1761.             return FAILURE;
  1762.         }
  1763.         }
  1764.         status = NetUltraSource(interPtr, &dgram.address, dgram.count,
  1765.             dgram.size, 
  1766.             (dgram.useBuffer == TRUE) ? (Address) dgram.buffer :
  1767.             (Address) NIL, &dgram.time);
  1768.         inSize = sizeof(dgram);
  1769.         outSize = ioctlPtr->outBufSize;
  1770.         fmtStatus = Fmt_Convert("{w2{w2}wb*}", mach_Format, &inSize,
  1771.         (Address) &dgram, ioctlPtr->format, &outSize,
  1772.         (Address) ioctlPtr->outBuffer);
  1773.         if (fmtStatus != 0) {
  1774.         if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
  1775.             return GEN_INVALID_ARG;
  1776.         } else {
  1777.             printf(
  1778.             "NetUltraIOControl: Fmt_Convert returned %d\n",
  1779.             fmtStatus);
  1780.             return FAILURE;
  1781.         }
  1782.         }
  1783.         break;
  1784.     }
  1785.     case IOC_ULTRA_SINK: {
  1786.         Dev_UltraSink        sink;
  1787.         int                value;
  1788.         outSize = sizeof(int);
  1789.         inSize = ioctlPtr->inBufSize;
  1790.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1791.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1792.                 (Address) &value);
  1793.         if (fmtStatus != 0) {
  1794.         printf("Format of IOC_ULTRA_TRACE parameter failed, 0x%x\n",
  1795.             fmtStatus);
  1796.         return GEN_INVALID_ARG;
  1797.         }
  1798.         outSize = ioctlPtr->outBufSize;
  1799.         sink.packets = packetsSunk;
  1800.         Timer_SubtractTicks(sinkEndTime, sinkStartTime, &sink.time);
  1801.         Timer_TicksToTime(sink.time, &sink.time);
  1802.         inSize = sizeof(sink);
  1803.         fmtStatus = Fmt_Convert("w{w2}", mach_Format, &inSize,
  1804.                 (Address) &sink, ioctlPtr->format, &outSize,
  1805.                 ioctlPtr->outBuffer);
  1806.         if (fmtStatus != 0) {
  1807.         printf("Format of IOC_ULTRA_TRACE parameter failed, 0x%x\n",
  1808.             fmtStatus);
  1809.         return GEN_INVALID_ARG;
  1810.         }
  1811.         if (value > 0) {
  1812.         statePtr->flags |= NET_ULTRA_STATE_SINK;
  1813.         statePtr->flags &= ~NET_ULTRA_STATE_NORMAL;
  1814.         packetsSunk = 0;
  1815.         } else {
  1816.         statePtr->flags &= ~NET_ULTRA_STATE_SINK;
  1817.         statePtr->flags |= NET_ULTRA_STATE_NORMAL;
  1818.         }
  1819.         break;
  1820.     }
  1821.     case IOC_ULTRA_COLLECT_STATS: {
  1822.         int        value;
  1823.         inSize = ioctlPtr->inBufSize;
  1824.         outSize = sizeof(int);
  1825.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1826.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1827.                 (Address) &value);
  1828.         if (fmtStatus != 0) {
  1829.         if (fmtStatus == FMT_INPUT_TOO_SMALL) {
  1830.             return GEN_INVALID_ARG;
  1831.         } else {
  1832.             printf("NetUltraIOControl: Fmt_Convert returned %d\n",
  1833.             fmtStatus);
  1834.             return FAILURE;
  1835.         }
  1836.         }
  1837.         if (value == TRUE) {
  1838.         statePtr->flags |= NET_ULTRA_STATE_STATS;
  1839.         } else {
  1840.         statePtr->flags &= ~NET_ULTRA_STATE_STATS;
  1841.         }
  1842.         break;
  1843.     }
  1844.     case IOC_ULTRA_CLEAR_STATS: {
  1845.         bzero((char *) &statePtr->stats, sizeof(statePtr->stats));
  1846.         break;
  1847.     }
  1848.     case IOC_ULTRA_GET_STATS: {
  1849.         outSize = ioctlPtr->outBufSize;
  1850.         inSize = sizeof(Dev_UltraStats);
  1851.         fmtStatus = Fmt_Convert("w*", mach_Format, &inSize,
  1852.                 (Address) &statePtr->stats, 
  1853.                 ioctlPtr->format, &outSize,
  1854.                 ioctlPtr->outBuffer);
  1855.         if (fmtStatus != 0) {
  1856.         printf("Format of IOC_ULTRA_GET_STATS parameter failed, 0x%x\n",
  1857.             fmtStatus);
  1858.         return GEN_INVALID_ARG;
  1859.         }
  1860.         break;
  1861.     }
  1862.     case IOC_ULTRA_MAP_THRESHOLD: {
  1863.         int                value;
  1864.         outSize = sizeof(int);
  1865.         inSize = ioctlPtr->inBufSize;
  1866.         fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
  1867.                 ioctlPtr->inBuffer, mach_Format, &outSize,
  1868.                 (Address) &value);
  1869.         if (fmtStatus != 0) {
  1870.         printf(
  1871.         "Format of IOC_ULTRA_MAP_THRESHOLD parameter failed, 0x%x\n",
  1872.             fmtStatus);
  1873.         return GEN_INVALID_ARG;
  1874.         }
  1875.         netUltraMapThreshold = value;
  1876.         break;
  1877.     }
  1878.     default: {
  1879.         printf("NetUltraIOControl: unknown ioctl 0x%x\n",
  1880.         ioctlPtr->command);
  1881.     }
  1882.  
  1883.     }
  1884.     return status;
  1885. }
  1886.  
  1887. /*
  1888.  *----------------------------------------------------------------------
  1889.  *
  1890.  * NetUltraSendReq --
  1891.  *
  1892.  *    Queue up a request for the adapter board. If there isn't
  1893.  *    any room in the queue then we block until there is.
  1894.  *
  1895.  * Results:
  1896.  *    Standard Sprite return status.
  1897.  *
  1898.  * Side effects:
  1899.  *    The adapter board is notified of the addition to the queue.
  1900.  *
  1901.  *----------------------------------------------------------------------
  1902.  */
  1903.  
  1904. ReturnStatus
  1905. NetUltraSendReq(statePtr, doneProc, data, rpc, scatterLength, scatterPtr, 
  1906.     requestSize, requestPtr)
  1907.     NetUltraState    *statePtr;    /* State of the adapter. */
  1908.     void        (*doneProc)();    /* Procedure to call when
  1909.                      * XRB is done. */
  1910.     ClientData        data;        /* Data used by doneProc. */
  1911.     Boolean        rpc;        /* Is this an RPC packet? */
  1912.     int            scatterLength;    /* Size of scatter/gather array. */
  1913.     Net_ScatterGather    *scatterPtr;    /* The scatter/gather array. */
  1914.     int            requestSize;    /* Size of the request. */
  1915.     NetUltraRequest    *requestPtr;    /* Request to be sent. */
  1916. {
  1917.     NetUltraXRB            *xrbPtr;
  1918.     NetUltraRequestHdr        *hdrPtr;
  1919.     NetUltraDMAInfo        *dmaPtr;
  1920.     ReturnStatus        status = SUCCESS;
  1921.     int                signal;
  1922.     NetUltraXRBInfo        *infoPtr;
  1923.     NetUltraTraceInfo        *tracePtr;
  1924.     int                size;
  1925.     int                i;
  1926.  
  1927.     if (netUltraDebug) {
  1928.     printf("NetUltraSendReq: sending a request\n");
  1929.     }
  1930.     xrbPtr = statePtr->nextToAdapterPtr;
  1931. #ifndef CLEAN
  1932.     if (netUltraTrace) {
  1933.     NEXT_TRACE(statePtr, &tracePtr);
  1934.     tracePtr->event = SEND_REQ;
  1935.     tracePtr->index = xrbPtr - statePtr->firstToAdapterPtr;
  1936.     Timer_GetCurrentTicks(&tracePtr->ticks);
  1937.     }
  1938. #endif
  1939.     if (statePtr->nextToAdapterPtr->filled) {
  1940. #ifndef CLEAN
  1941.     if (netUltraTrace) {
  1942.         NEXT_TRACE(statePtr, &tracePtr);
  1943.         tracePtr->event = TO_ADAPTER_FILLED;
  1944.         tracePtr->index = statePtr->nextToAdapterPtr - 
  1945.         statePtr->firstToAdapterPtr;
  1946.     }
  1947. #endif
  1948.     do {
  1949.         if (netUltraDebug) {
  1950.         printf("NetUltraSendReq: no XRB free, waiting\n");
  1951.         }
  1952.         statePtr->toAdapterAvail.waiting = TRUE;
  1953.         signal = Sync_SlowMasterWait(
  1954.             (unsigned int) &statePtr->toAdapterAvail,
  1955.             &statePtr->interPtr->mutex, TRUE);
  1956.         if (signal) {
  1957.         return GEN_ABORTED_BY_SIGNAL;
  1958.         }
  1959.     } while(statePtr->nextToAdapterPtr->filled);
  1960.     }
  1961.     xrbPtr = statePtr->nextToAdapterPtr;
  1962.     hdrPtr = (NetUltraRequestHdr *) requestPtr;
  1963.     infoPtr = (NetUltraXRBInfo *) List_First(statePtr->freeXRBInfoList);
  1964.     if ((List_Links *) infoPtr == statePtr->freeXRBInfoList) {
  1965.     panic("NetUltraSendReq: no available XRBInfo structures!");
  1966.     }
  1967.     List_Remove((List_Links *) infoPtr);
  1968.     List_Insert((List_Links *) infoPtr, 
  1969.     LIST_ATFRONT(statePtr->pendingXRBInfoList));
  1970.     infoPtr->doneProc = doneProc;
  1971.     infoPtr->doneData = data;
  1972.     infoPtr->xrbPtr = xrbPtr;
  1973.     infoPtr->scatterPtr = scatterPtr;
  1974.     infoPtr->scatterLength = scatterLength;
  1975.     infoPtr->requestSize = requestSize;
  1976.     infoPtr->requestPtr = (union NetUltraRequest *) requestPtr;
  1977.     infoPtr->flags = NET_ULTRA_INFO_PENDING;
  1978. #ifndef CLEAN
  1979.     if (netUltraDebug) {
  1980.     printf("NetUltraSendReq: using 0x%x\n", infoPtr);
  1981.     }
  1982. #endif
  1983. #ifndef CLEAN
  1984.     if (netUltraTrace) {
  1985.     NEXT_TRACE(statePtr, &tracePtr);
  1986.     tracePtr->event = SEND_REQ_INFO;
  1987.     tracePtr->index = xrbPtr - statePtr->firstToAdapterPtr;
  1988.     tracePtr->infoPtr = infoPtr;
  1989.     }
  1990. #endif
  1991.     hdrPtr->infoPtr = infoPtr;
  1992.     hdrPtr->status = 0;
  1993.     hdrPtr->reference = 0;
  1994.     if (scatterLength > 0) {
  1995.     Address        buffer;
  1996.     List_Links    *itemPtr;
  1997.     /*
  1998.      * If the buffer is not in DVMA space then get one that is.
  1999.      */
  2000.     if (! DVMA_ADDRESS(scatterPtr[0].bufAddr, statePtr)) {
  2001.         if (netUltraDebug) {
  2002.         printf("Data is not in DVMA space.\n");
  2003.         }
  2004.         while(List_IsEmpty(statePtr->freeBufferList)) {
  2005.         int        signal;
  2006.         statePtr->bufferAvail.waiting = TRUE;
  2007.         signal = Sync_SlowMasterWait(
  2008.             (unsigned int) &statePtr->bufferAvail,
  2009.             &statePtr->interPtr->mutex, TRUE);
  2010.         if (signal) {
  2011.             status = GEN_ABORTED_BY_SIGNAL;
  2012.             goto exit;
  2013.         }
  2014.         }
  2015.         itemPtr = List_First(statePtr->freeBufferList);
  2016.         if (itemPtr == statePtr->freeBufferList) {
  2017.         panic("NetUltraOutput: list screwup\n");
  2018.         }
  2019.         List_Remove(itemPtr);
  2020.         buffer = (Address) itemPtr;
  2021.         infoPtr->flags |= NET_ULTRA_INFO_STD_BUFFER;
  2022.         if (rpc) {
  2023.         int    lastIndex;
  2024.         /*
  2025.          * This is a standard RPC packet with 4 parts --
  2026.          * packet header, RPC header, RPC params, and data. 
  2027.          */
  2028.         size = 0;
  2029.         lastIndex = scatterLength - 1;
  2030.         for (i = 0; i < scatterLength; i++) {
  2031.             size += scatterPtr[i].length;
  2032.         }
  2033.         Net_GatherCopy(scatterPtr, scatterLength, buffer);
  2034.         } else {
  2035.  
  2036.         if (netUltraDebug) {
  2037.             printf("Copying data into DVMA space.\n");
  2038.         }
  2039.         Net_GatherCopy(scatterPtr, 1, buffer);
  2040.         size = scatterPtr[0].length;
  2041.         }
  2042.     } else {
  2043.         /* 
  2044.          * The data is already in DVMA space.  It had better be contiguous!
  2045.          */
  2046.         if (netUltraDebug) {
  2047.         printf("Data is already in DVMA space.\n");
  2048.         }
  2049.         buffer = scatterPtr[0].bufAddr;
  2050.         size = scatterPtr[0].length;
  2051.     }
  2052.     if (! DVMA_ADDRESS(buffer, statePtr)) {
  2053.         buffer = BUFFER_TO_DVMA(buffer, statePtr);
  2054.     }
  2055.     hdrPtr->buffer = DVMA_TO_VME(buffer, statePtr);
  2056.     hdrPtr->size = size;
  2057.     } else {
  2058.     hdrPtr->size = 0;
  2059.     }
  2060.     if (netUltraDebug) {
  2061.     printf("NetUltraSendReq: hdrPtr->buffer = 0x%x, size = %d\n",
  2062.         hdrPtr->buffer, hdrPtr->size);
  2063.     }
  2064. #ifndef CLEAN
  2065.     if (statePtr->flags & NET_ULTRA_STATE_STATS) {
  2066.     if (hdrPtr->cmd == NET_ULTRA_DGRAM_SEND_REQ) {
  2067.         statePtr->stats.packetsSent++;
  2068.         statePtr->stats.bytesSent += hdrPtr->size;
  2069.         statePtr->stats.sentHistogram[hdrPtr->size >> 10]++;
  2070.     }
  2071.     }
  2072. #endif
  2073.     bcopy((char *) requestPtr, (char *) &xrbPtr->request, requestSize);
  2074.     dmaPtr = &xrbPtr->dma;
  2075.     if (hdrPtr->cmd == NET_ULTRA_DGRAM_SEND_REQ) {
  2076.     dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB_DATA;
  2077.     statePtr->numWritePending++;
  2078. #ifndef CLEAN
  2079.     if (netUltraDebug) {
  2080.         printf("NetUltraSendReq: number of pending writes = %d.\n",
  2081.         statePtr->numWritePending);
  2082.     }
  2083. #endif
  2084.     if (statePtr->numWritePending > statePtr->maxWritePending) {
  2085.         panic("NetUltraSendReq: too many writes.\n");
  2086.     }
  2087.     } else if (hdrPtr->cmd == NET_ULTRA_DGRAM_RECV_REQ) {
  2088.     dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB;
  2089.     statePtr->numReadPending++;
  2090. #ifndef CLEAN
  2091.     if (netUltraDebug) {
  2092.         printf("NetUltraSendReq: number of pending reads = %d.\n",
  2093.         statePtr->numReadPending);
  2094.     }
  2095. #endif
  2096.     if (statePtr->numReadPending > statePtr->maxReadPending) {
  2097.         panic("NetUltraSendReq: too many reads.\n");
  2098.     }
  2099.     } else {
  2100.     dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB;
  2101.     }
  2102.     dmaPtr->id = 0;
  2103.     dmaPtr->reference = 0;
  2104.     dmaPtr->offset = 0;
  2105.     dmaPtr->infoPtr = (NetUltraXRBInfo *) NIL;
  2106.     dmaPtr->length = requestSize;
  2107.     /*
  2108.      * Set the filled field so the adapter will process the XRB.
  2109.      */
  2110.     if (netUltraDebug) {
  2111.     printf("NetUltraSendReq: xrbPtr = 0x%x\n", xrbPtr);
  2112.     }
  2113.     xrbPtr->filled = 1;
  2114.     if (statePtr->nextToAdapterPtr == statePtr->lastToAdapterPtr) {
  2115.     statePtr->nextToAdapterPtr = statePtr->firstToAdapterPtr;
  2116.     } else {
  2117.     statePtr->nextToAdapterPtr++;
  2118.     }
  2119.     /*
  2120.      * Poke the adapter by setting the address register to 0. This
  2121.      * tells it to look in the queue.
  2122.      */
  2123.     *statePtr->intrReg = 0;
  2124. #ifndef CLEAN
  2125.     if (netUltraDebug) {
  2126.     printf("NetUltraSendReq: returning\n");
  2127.     }
  2128. #endif
  2129. exit:
  2130.     return status;
  2131. }
  2132.  
  2133. /*
  2134.  *----------------------------------------------------------------------
  2135.  *
  2136.  * GetStatusString --
  2137.  *
  2138.  *    Returns a string corresponding to the given status (status
  2139.  *    is a field in a NetUltraRequestHdr.
  2140.  *
  2141.  * Results:
  2142.  *    Ptr to string describing the status.
  2143.  *
  2144.  * Side effects:
  2145.  *    None.
  2146.  *
  2147.  *----------------------------------------------------------------------
  2148.  */
  2149.  
  2150. static char *
  2151. GetStatusString(status)
  2152.     unsigned char    status;
  2153. {
  2154.     static char *statusMsg[] = {
  2155.     "Unknown",                /* 0 */
  2156.     "OK",                    /* 1 */
  2157.     "FAIL: invalid request",        /* 2 */
  2158.     "OK: EOM",                /* 3 */
  2159.     "FAIL: no resources",            /* 4 */
  2160.     "OK: decide",                /* 5 */
  2161.     "FAIL: unknown reference",        /* 6 */
  2162.     "OK: closed",                /* 7 */
  2163.     "FAIL: buffer too small",        /* 8 */
  2164.     "OK; withdrawn",            /* 9 */
  2165.     "FAIL: buffer too large",        /* 10 */
  2166.     "OK: reject connection",        /* 11 */
  2167.     "FAIL: illegal request",        /* 12 */
  2168.     "OK: connection request",        /* 13 */
  2169.     "FAIL: REM abort",            /* 14 */
  2170.     "OK: closing",                /* 15 */
  2171.     "FAIL: LOC timeout",            /* 16 */
  2172.     "OK: timed-out",            /* 17 */
  2173.     "FAIL: unknown connection class",     /* 18 */
  2174.     "OK: out of sequence",            /* 19 */
  2175.     "FAIL: duplicate request",        /* 20 */
  2176.     "Unknown",                /* 21 */
  2177.     "FAIL: connection rejected",        /* 22 */
  2178.     "Unknown",                /* 23 */
  2179.     "FAIL: negotiation failed",        /* 24 */
  2180.     "Unknown",                /* 25 */
  2181.     "FAIL: illegal address",        /* 26 */
  2182.     "Unknown",                /* 27 */
  2183.     "FAIL: network error",            /* 28 */
  2184.     "Unknown",                /* 29 */
  2185.     "FAIL: protocol error",            /* 30 */
  2186.     "Unknown",                /* 31 */
  2187.     "FAIL: illegal RB length",        /* 32 */
  2188.     "Unknown",                /* 33 */
  2189.     "FAIL: unknown SAP id",            /* 34 */
  2190.     "Unknown",                /* 35 */
  2191.     "FAIL: zero RB id",            /* 36 */
  2192.     "Unknown",                /* 37 */
  2193.     "FAIL: adapter down",            /* 38 */
  2194.     };
  2195.     static int numStatusMsg = sizeof(statusMsg) / sizeof(char *);
  2196.  
  2197.     if (status >= numStatusMsg) {
  2198.     return "Unknown";
  2199.     } else {
  2200.     return statusMsg[status];
  2201.     }
  2202. }
  2203.  
  2204. /*
  2205.  *----------------------------------------------------------------------
  2206.  *
  2207.  * InitQueues --
  2208.  *
  2209.  *    Initializes the XRB queues.
  2210.  *
  2211.  * Results:
  2212.  *    None.
  2213.  *
  2214.  * Side effects:
  2215.  *    Memory is allocated and mapped into DMA space if necessary.
  2216.  *
  2217.  *----------------------------------------------------------------------
  2218.  */
  2219.  
  2220. static void
  2221. InitQueues(statePtr)
  2222.     NetUltraState    *statePtr;    /* State of the adapter. */
  2223. {
  2224.     int        size;
  2225.     Address    addr;
  2226.     List_Links    *itemPtr;
  2227.     int        i;
  2228.  
  2229.     if (!(statePtr->queuesInit)) {
  2230.     /*
  2231.      * Allocate XRBs that go from the adapter to the host. 
  2232.      */
  2233.     size = sizeof(NetUltraXRB) * NET_ULTRA_NUM_TO_HOST;
  2234.     addr = (Address) malloc(size);
  2235.     addr = VmMach_DMAAlloc(size, (Address) addr);
  2236.     if (addr == (Address) NIL) {
  2237.         panic("NetUltraInit: unable to allocate DMA space.\n");
  2238.     }
  2239.     statePtr->firstToHostPtr = (NetUltraXRB *) addr;
  2240.     /* 
  2241.      * Allocate XRBs that go from the host to the adapter. 
  2242.      */
  2243.     size = sizeof(NetUltraXRB) * NET_ULTRA_NUM_TO_ADAPTER;
  2244.     addr = (Address) malloc(size);
  2245.     addr = VmMach_DMAAlloc(size, (Address) addr);
  2246.     if (addr == (Address) NIL) {
  2247.         panic("NetUltraInit: unable to allocate DMA space.\n");
  2248.     }
  2249.     statePtr->firstToAdapterPtr = (NetUltraXRB *) addr;
  2250.     statePtr->pendingXRBInfoList = &statePtr->pendingXRBInfoListHdr;
  2251.     statePtr->freeXRBInfoList = &statePtr->freeXRBInfoListHdr;
  2252.     List_Init(statePtr->pendingXRBInfoList);
  2253.     List_Init(statePtr->freeXRBInfoList);
  2254.     for (i = 0; i < NET_ULTRA_NUM_TO_ADAPTER + NET_ULTRA_NUM_TO_HOST; i++) {
  2255.         itemPtr = (List_Links *) malloc(sizeof(NetUltraXRBInfo));
  2256.         List_InitElement(itemPtr);
  2257.         List_Insert(itemPtr, LIST_ATREAR(statePtr->freeXRBInfoList));
  2258.     }
  2259.     /*
  2260.      * Allocate buffers in DVMA space for pending reads and writes. 
  2261.      */
  2262.     statePtr->maxReadPending = NET_ULTRA_PENDING_READS;
  2263.     statePtr->numReadPending = 0;
  2264.     statePtr->maxWritePending = NET_ULTRA_PENDING_WRITES;
  2265.     statePtr->numWritePending = 0;
  2266.     statePtr->numBuffers = statePtr->maxReadPending + 
  2267.         statePtr->maxWritePending;
  2268.     statePtr->bufferSize = NET_ULTRA_MAX_BYTES;
  2269.     size = statePtr->numBuffers * statePtr->bufferSize;
  2270.     addr = (Address) malloc(size);
  2271.     statePtr->buffers = addr;
  2272.     addr = VmMach_DMAAlloc(size, (Address) addr);
  2273.     statePtr->buffersDVMA = addr;
  2274.     statePtr->freeBufferList = &statePtr->freeBufferListHdr;
  2275.  
  2276.     statePtr->queuesInit = TRUE;
  2277.     }
  2278.     statePtr->lastToHostPtr = statePtr->firstToHostPtr + 
  2279.         NET_ULTRA_NUM_TO_HOST - 1;
  2280.     statePtr->nextToHostPtr = statePtr->firstToHostPtr;
  2281.     statePtr->lastToAdapterPtr = statePtr->firstToAdapterPtr + 
  2282.         NET_ULTRA_NUM_TO_ADAPTER - 1;
  2283.     statePtr->nextToAdapterPtr = statePtr->firstToAdapterPtr;
  2284.     size = sizeof(NetUltraXRB) * NET_ULTRA_NUM_TO_HOST;
  2285.     bzero((char *) statePtr->firstToHostPtr, size);
  2286.     size = sizeof(NetUltraXRB) * NET_ULTRA_NUM_TO_ADAPTER;
  2287.     bzero((char *) statePtr->firstToAdapterPtr, size);
  2288.     while (!List_IsEmpty(statePtr->pendingXRBInfoList)) {
  2289.     itemPtr = List_First(statePtr->pendingXRBInfoList);
  2290.     List_Remove(itemPtr);
  2291.     List_Insert(itemPtr, LIST_ATREAR(statePtr->freeXRBInfoList));
  2292.     }
  2293.     bzero((char *) statePtr->buffers, statePtr->numBuffers * 
  2294.     statePtr->bufferSize);
  2295.     List_Init(statePtr->freeBufferList);
  2296.     for (i = 0; i < statePtr->numBuffers; i++) {
  2297.     itemPtr = (List_Links *) 
  2298.         (statePtr->buffers + (i * statePtr->bufferSize));
  2299.     List_InitElement(itemPtr);
  2300.     List_Insert(itemPtr, LIST_ATREAR(statePtr->freeBufferList));
  2301.     }
  2302. }
  2303.  
  2304. /*
  2305.  *----------------------------------------------------------------------
  2306.  *
  2307.  * NetUltraPendingRead --
  2308.  *
  2309.  *    Send a pending read to the adapter.
  2310.  *
  2311.  * Results:
  2312.  *    Standard Sprite return status.
  2313.  *
  2314.  * Side effects:
  2315.  *    A "read datagram" XRB is sent to the adapter.
  2316.  *
  2317.  *----------------------------------------------------------------------
  2318.  */
  2319.  
  2320. ReturnStatus
  2321. NetUltraPendingRead(interPtr, size, buffer)
  2322.     Net_Interface    *interPtr;    /* Interface to read from. */
  2323.     int            size;        /* Size of the data buffer. */
  2324.     Address        buffer;        /* Address of the buffer in DMA space */
  2325. {
  2326.     NetUltraState        *statePtr;
  2327.     NetUltraRequest        request;
  2328.     NetUltraDatagramRequest    *dgramReqPtr;
  2329.     NetUltraRequestHdr        *hdrPtr;
  2330.     ReturnStatus        status = SUCCESS;
  2331.     Net_ScatterGather        scatter;
  2332.  
  2333.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2334.     if (!(statePtr->flags & NET_ULTRA_STATE_START)) {
  2335.     printf("NetUltraPendingRead: adapter not started!\n");
  2336.     return FAILURE;
  2337.     }
  2338. #ifndef CLEAN
  2339.     if (netUltraDebug) {
  2340.     printf("NetUltraPendingRead: queuing a pending read.\n");
  2341.     printf("Buffer size = %d, buffer = 0x%x\n", size, buffer);
  2342.     }
  2343. #endif
  2344.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2345.     bzero((char *) &request, sizeof(request));
  2346.     dgramReqPtr = &request.dgram;
  2347.     hdrPtr = &dgramReqPtr->hdr;
  2348.     dgramReqPtr->remoteAddress = wildcardAddress;
  2349.     dgramReqPtr->localAddress = wildcardAddress;
  2350.     hdrPtr->cmd = NET_ULTRA_DGRAM_RECV_REQ;
  2351.     /*
  2352.      * Save room at the beginning of the buffer for the datagram request
  2353.      * block.  The higher-level software expects the packet header to
  2354.      * proceed the packet (this should be fixed sometime).
  2355.      */
  2356.     buffer += sizeof(NetUltraDatagramRequest);
  2357.     size -= sizeof(NetUltraDatagramRequest);
  2358.     scatter.bufAddr = buffer;
  2359.     scatter.length = size;
  2360.     status = NetUltraSendReq(statePtr, ReadDone, (ClientData) 0, FALSE,  
  2361.     1, &scatter, sizeof(NetUltraDatagramRequest), &request);
  2362.     if (status != SUCCESS) {
  2363.     printf("NetUltraPendingRead: could not send request to adapter\n");
  2364.     }
  2365. #ifndef CLEAN
  2366.     if (netUltraDebug) {
  2367.     printf("NetUltraPendingRead: returning.\n");
  2368.     }
  2369. #endif
  2370.     return status;
  2371. }
  2372.  
  2373. /*
  2374.  *----------------------------------------------------------------------
  2375.  *
  2376.  * ReadDone --
  2377.  *
  2378.  *    This routine is called from the interrupt handler when a read
  2379.  *    request completes.
  2380.  *
  2381.  * Results:
  2382.  *    None.
  2383.  *
  2384.  * Side effects:
  2385.  *    None.
  2386.  *
  2387.  *----------------------------------------------------------------------
  2388.  */
  2389.  
  2390. static void
  2391. ReadDone(interPtr, infoPtr)
  2392.     Net_Interface    *interPtr;    /* Interface. */
  2393.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  2394. {
  2395.     NetUltraXRB            *xrbPtr;
  2396.     NetUltraDatagramRequest    *reqPtr;
  2397.     NetUltraRequestHdr        *hdrPtr;
  2398.     NetUltraState        *statePtr;
  2399.     int                size;
  2400.     Address            buffer = (Address) NIL;
  2401.     ReturnStatus        status = SUCCESS;
  2402.  
  2403.     xrbPtr = infoPtr->xrbPtr;
  2404.     reqPtr = &xrbPtr->request.dgram;
  2405.     hdrPtr = &reqPtr->hdr;
  2406.  
  2407.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2408.     if (!(hdrPtr->status & NET_ULTRA_STATUS_OK)) {
  2409.     panic("ReadDone: read failed 0x%x (continuable)\n", hdrPtr->status);
  2410.     } else {
  2411. #ifndef CLEAN
  2412.     if (netUltraDebug) {
  2413.         char    local[32];
  2414.         char    remote[32];
  2415.         printf("ReadDone: received a packet.\n");
  2416.         *local = '\0';
  2417.         *remote = '\0';
  2418.         (void) Net_UltraAddrToString(&reqPtr->localAddress.address, 
  2419.             local);
  2420.         (void) Net_UltraAddrToString(&reqPtr->remoteAddress.address, 
  2421.             remote);
  2422.         printf("Local address: %s\n", local);
  2423.         printf("Remote address: %s\n", remote);
  2424.         printf("Data size = %d\n", hdrPtr->size);
  2425.         if (hdrPtr->size > 0) {
  2426.         printf("Data: %s\n", hdrPtr->buffer + VMMACH_DMA_START_ADDR);
  2427.         }
  2428.     }
  2429. #endif
  2430.     /*
  2431.      * Adjust size and start of buffer to account for the space
  2432.      * for the request block.
  2433.      */
  2434.     buffer = VME_TO_BUFFER(hdrPtr->buffer, statePtr) -
  2435.             sizeof(NetUltraDatagramRequest);
  2436.     size = hdrPtr->size + sizeof(NetUltraDatagramRequest);
  2437.     if (statePtr->flags & NET_ULTRA_STATE_NORMAL) {
  2438.         /* 
  2439.          * Copy the request block (packet header) to the start of the
  2440.          * packet. 
  2441.          */
  2442.  
  2443.         *((NetUltraDatagramRequest *) buffer) = *reqPtr;
  2444.         /*
  2445.          * Release the lock around interface so that the RPC system
  2446.          * can output a packet in response to this one.  The XRB is
  2447.          * still marked as filled, so the adapter won't overwrite it.
  2448.          * Also the XRBinfo is not marked as pending, so the interrupt
  2449.          * routine won't re-process the packet should it loop around
  2450.          * the queue before Net_Input returns.
  2451.          */
  2452.         MASTER_UNLOCK(&interPtr->mutex);
  2453.         Net_Input(interPtr, buffer, size);
  2454.         MASTER_LOCK(&interPtr->mutex);
  2455.     } else if (statePtr->flags & NET_ULTRA_STATE_ECHO) {
  2456.         Net_ScatterGather        tmpScatter;
  2457.         if (netUltraDebug) {
  2458.         printf("ReadDone: returning datagram to sender.\n");
  2459.         }
  2460.         hdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  2461.         hdrPtr->status = 0;
  2462.         tmpScatter.bufAddr = BUFFER_TO_DVMA(buffer, statePtr);
  2463.         tmpScatter.length = hdrPtr->size;
  2464.         status = NetUltraSendReq(statePtr, EchoDone, (ClientData) NIL, 
  2465.             FALSE, 1, &tmpScatter,sizeof(NetUltraDatagramRequest),
  2466.             (NetUltraRequest *) reqPtr);
  2467.         if (status != SUCCESS) {
  2468.         panic("ReadDone: unable to return datagram to sender.\n");
  2469.         }
  2470.     } else if (statePtr->flags & NET_ULTRA_STATE_DSND_TEST) {
  2471.         Net_ScatterGather        tmpScatter;
  2472.         dsndCount--;
  2473.         if (dsndCount > 0) {
  2474.         if (netUltraDebug) {
  2475.             printf("ReadDone: returning datagram to sender.\n");
  2476.         }
  2477.         hdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  2478.         hdrPtr->status = 0;
  2479.         tmpScatter.bufAddr = BUFFER_TO_DVMA(buffer, statePtr);
  2480.         tmpScatter.length = hdrPtr->size;
  2481.         status = NetUltraSendReq(statePtr, EchoDone, (ClientData) NIL, 
  2482.                 FALSE, 1, &tmpScatter,
  2483.                 sizeof(NetUltraDatagramRequest),
  2484.                 (NetUltraRequest *) reqPtr);
  2485.         if (status != SUCCESS) {
  2486.             panic("ReadDone: unable to return datagram to sender.\n");
  2487.         }
  2488.         } else {
  2489.  
  2490.         /*
  2491.          * Notify the waiting process that the last datagram has
  2492.          * arrived.
  2493.          */
  2494.         Sync_Broadcast(&dsndTestDone);
  2495.         }
  2496.     } else if (statePtr->flags & NET_ULTRA_STATE_SINK) {
  2497.         packetsSunk++;
  2498.     }
  2499.     }
  2500.     statePtr->numReadPending--;
  2501.     if (statePtr->numReadPending < 0) {
  2502.     panic("ReadDone: number of pending reads < 0.\n");
  2503.     }
  2504.     /* 
  2505.      * This may introduce a deadlock if the queues are of size 1, 
  2506.      * since the XRB and info structures are
  2507.      * not freed until this routine (ReadDone) returns, and 
  2508.      * NetUltraPendingRead needs to use these structures.  If the queues
  2509.      * are greater than 1 then NetUltraPendingRead may have to
  2510.      * wait for an XRB to free up, but that should be ok.
  2511.      */
  2512.     status = NetUltraPendingRead(interPtr, statePtr->bufferSize, 
  2513.         BUFFER_TO_DVMA(buffer,statePtr));
  2514.     if (status != SUCCESS) {
  2515.     printf("ReadDone: could not queue next pending read.\n");
  2516.     }
  2517. #ifndef CLEAN
  2518.     if (netUltraDebug) {
  2519.     printf("ReadDone: returning.\n");
  2520.     }
  2521. #endif
  2522. }
  2523.  
  2524. /*
  2525.  *----------------------------------------------------------------------
  2526.  *
  2527.  * EchoDone --
  2528.  *
  2529.  *    This routine is called when the write of a datagram that is
  2530.  *    being echoed back to the sender completes.  All it does is
  2531.  *    decrement the number of pending writes.
  2532.  *
  2533.  * Results:
  2534.  *    None.
  2535.  *
  2536.  * Side effects:
  2537.  *    None.
  2538.  *
  2539.  *----------------------------------------------------------------------
  2540.  */
  2541.  
  2542. /*ARGSUSED*/
  2543. static void
  2544. EchoDone(interPtr, infoPtr)
  2545.     Net_Interface    *interPtr;    /* Interface. */
  2546.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  2547. {
  2548.     NetUltraState    *statePtr;
  2549.  
  2550.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2551.     statePtr->numWritePending--;
  2552. }
  2553.  
  2554.  
  2555. /*
  2556.  *----------------------------------------------------------------------
  2557.  *
  2558.  * NetUltraSendDgram --
  2559.  *
  2560.  *    This routine will send a datagram to the specified host.  It
  2561.  *    is intended for debugging purposes.  
  2562.  *
  2563.  * Results:
  2564.  *    None.
  2565.  *
  2566.  * Side effects:
  2567.  *    A write is queued to the adapter.
  2568.  *
  2569.  *----------------------------------------------------------------------
  2570.  */
  2571.  
  2572. static ReturnStatus
  2573. NetUltraSendDgram(interPtr, netAddressPtr, count, bufSize, buffer, timePtr)
  2574.     Net_Interface    *interPtr;        /* Interface to send on. */
  2575.     Net_Address        *netAddressPtr;        /* Host to send to. */
  2576.     int            count;            /* Number of times to send
  2577.                          * datagram. */
  2578.     int            bufSize;        /* Size of data buffer. */
  2579.     Address        buffer;            /* Data to send. */
  2580.     Time        *timePtr;        /* Place to store total 
  2581.                          * time to send datagrams. */
  2582. {
  2583.     NetUltraState        *statePtr;
  2584.     NetUltraRequest        request;
  2585.     NetUltraDatagramRequest    *dgramReqPtr;
  2586.     NetUltraRequestHdr        *hdrPtr;
  2587.     ReturnStatus        status;
  2588.     Timer_Ticks         startTime;
  2589.     Timer_Ticks         endTime;
  2590.     Timer_Ticks         curTime;
  2591.     NetUltraTraceInfo        *tracePtr;
  2592.     Net_ScatterGather        scatter;
  2593.     char            *ptr;
  2594.  
  2595.     MASTER_LOCK(&interPtr->mutex);
  2596. #ifndef CLEAN
  2597.     if (netUltraDebug) {
  2598.     char    address[100];
  2599.     (void) Net_AddrToString(netAddressPtr,  address);
  2600.     printf("NetUltraSendDgram: sending to %s\n", address);
  2601.     }
  2602. #endif
  2603.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2604.     if (!(statePtr->flags & NET_ULTRA_STATE_START)) {
  2605.     printf("NetUltraSendDgram: adapter not started!\n");
  2606.     status = FAILURE;
  2607.     goto exit;
  2608.     }
  2609.     bzero((char *) &request, sizeof(request));
  2610.     dgramReqPtr = &request.dgram;
  2611.     hdrPtr = &dgramReqPtr->hdr;
  2612.     dgramReqPtr->remoteAddress = wildcardAddress;
  2613.     dgramReqPtr->remoteAddress.tsapSize = 2;
  2614.     dgramReqPtr->remoteAddress.tsap[1] = 1;
  2615.     dgramReqPtr->remoteAddress.address = netAddressPtr->address.ultra;
  2616.     ptr = (char *) &dgramReqPtr->remoteAddress.address;
  2617.     ptr[1] = 0x49;
  2618.     ptr[6] = 0xfe;
  2619.     dgramReqPtr->localAddress = wildcardAddress;
  2620.     dgramReqPtr->localAddress.tsapSize = 2;
  2621.     dgramReqPtr->localAddress.tsap[1] = 1;
  2622.     dgramReqPtr->localAddress.address = 
  2623.     interPtr->netAddress[NET_PROTO_RAW].address.ultra;
  2624.     ptr = (char *) &dgramReqPtr->localAddress.address;
  2625.     ptr[1] = 0x49;
  2626.     ptr[6] = 0xfe;
  2627.     hdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  2628.     scatter.bufAddr = buffer;
  2629.     scatter.length = bufSize;
  2630.     statePtr->flags |= NET_ULTRA_STATE_DSND_TEST;
  2631.     statePtr->flags &= ~NET_ULTRA_STATE_NORMAL;
  2632.     dsndCount = count;
  2633. #ifndef CLEAN
  2634.     if (netUltraTrace) {
  2635.     NEXT_TRACE(statePtr, &tracePtr);
  2636.     tracePtr->event = DSND;
  2637.     Timer_GetCurrentTicks(&curTime);
  2638.     tracePtr->ticks = curTime;
  2639.     }
  2640. #endif
  2641.     Timer_GetCurrentTicks(&startTime);
  2642.     status = NetUltraSendReq(statePtr, DgramSendDone, (ClientData) NIL,
  2643.         FALSE, 1, &scatter, sizeof(NetUltraDatagramRequest), &request);
  2644.     Sync_MasterWait(&(dsndTestDone), &(interPtr->mutex), FALSE);
  2645.     Timer_GetCurrentTicks(&endTime);
  2646. #ifndef CLEAN
  2647.     if (netUltraDebug) {
  2648.     printf("NetUltraSendDgram: test done.\n");
  2649.     } 
  2650. #endif
  2651.     statePtr->flags &= ~NET_ULTRA_STATE_DSND_TEST;
  2652.     statePtr->flags |= NET_ULTRA_STATE_NORMAL;
  2653.     Timer_SubtractTicks(endTime, startTime, &endTime);
  2654.     Timer_TicksToTime(endTime, timePtr);
  2655. exit:
  2656.     MASTER_UNLOCK(&interPtr->mutex);
  2657.     return status;
  2658. }
  2659.  
  2660. /*
  2661.  *----------------------------------------------------------------------
  2662.  *
  2663.  * DgramSendDone --
  2664.  *
  2665.  *    Called by the interrupt handler when the datagram sent by 
  2666.  *     NetUltraSendDgram is actually sent.
  2667.  *
  2668.  * Results:
  2669.  *    None.
  2670.  *
  2671.  * Side effects:
  2672.  *    The process waiting for the datagram to be sent is notified.
  2673.  *
  2674.  *----------------------------------------------------------------------
  2675.  */
  2676.  
  2677. static void
  2678. DgramSendDone(interPtr, infoPtr)
  2679.     Net_Interface    *interPtr;    /* Interface. */
  2680.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  2681. {
  2682.     NetUltraXRB            *xrbPtr;
  2683.     NetUltraDatagramRequest    *reqPtr;
  2684.     NetUltraRequestHdr        *hdrPtr;
  2685.  
  2686.     xrbPtr = infoPtr->xrbPtr;
  2687.     reqPtr = &xrbPtr->request.dgram;
  2688.     hdrPtr = &reqPtr->hdr;
  2689.  
  2690.     if (!(hdrPtr->status & NET_ULTRA_STATUS_OK)) {
  2691.     panic("DgramSendDone: dgram send failed 0x%x\n", hdrPtr->status);
  2692.     } else {
  2693. #ifndef CLEAN
  2694.     if (netUltraDebug) {
  2695.         printf("DgramSendDone: datagram sent ok\n");
  2696.     }
  2697. #endif
  2698.     }
  2699.     ((NetUltraState *) interPtr->interfaceData)->numWritePending--;
  2700.     if (((NetUltraState *) interPtr->interfaceData)->numWritePending < 0) {
  2701.     panic("DgramSendDone: number of pending writes < 0.\n");
  2702.     }
  2703.     if (infoPtr->doneData != (ClientData) NIL) {
  2704.     Sync_Broadcast((Sync_Condition *) infoPtr->doneData);
  2705.     }
  2706. #ifndef CLEAN
  2707.     if (netUltraDebug) {
  2708.     printf("DgramSendDone: returning.\n");
  2709.     }
  2710. #endif
  2711.  
  2712. }
  2713.  
  2714.  
  2715. /*
  2716.  *----------------------------------------------------------------------
  2717.  *
  2718.  * NetUltraOutput --
  2719.  *
  2720.  *    Puts the outgoing packet into the queue to the adapter.
  2721.  *    Since the ultranet adapter does not to scatter/gather
  2722.  *    we have to get a free write buffer and copy the data
  2723.  *    into the buffer.
  2724.  *
  2725.  * Results:
  2726.  *    None.
  2727.  *
  2728.  * Side effects:
  2729.  *    The packet is put into the queue and the adapter is notified.
  2730.  *
  2731.  *----------------------------------------------------------------------
  2732.  */
  2733.  
  2734. ReturnStatus
  2735. NetUltraOutput(interPtr, hdrPtr, scatterGatherPtr, scatterGatherLength, rpc,
  2736.         statusPtr)
  2737.     Net_Interface        *interPtr;    /* The interface to use. */
  2738.     Address            hdrPtr;        /* Packet header. */
  2739.     Net_ScatterGather        *scatterGatherPtr; /* Scatter/gather elements.*/
  2740.     int                scatterGatherLength; /* Number of elements in
  2741.                               * scatter/gather list. */
  2742.     Boolean            rpc;        /* Is this an RPC packet? */
  2743.     ReturnStatus        *statusPtr;    /* Place to store status. */
  2744. {
  2745.     NetUltraState        *statePtr;
  2746.     ReturnStatus        status = SUCCESS;
  2747.     Net_UltraHeader        *ultraHdrPtr = (Net_UltraHeader *) hdrPtr;
  2748.  
  2749.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2750.     if ((ultraHdrPtr->cmd != NET_ULTRA_DGRAM_SEND_REQ) && 
  2751.     (ultraHdrPtr->cmd != 0)) {
  2752.     printf("Invalid header to NetUltraOutput.\n");
  2753.     return FAILURE;
  2754.     }
  2755.     /*
  2756.      * If the cmd is 0 then the packet is from the network device.
  2757.      */
  2758.     if (ultraHdrPtr->cmd == 0) {
  2759.     ultraHdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  2760.     }
  2761.     MASTER_LOCK(&interPtr->mutex);
  2762.     if (netUltraDebug) {
  2763.     char    address[100];
  2764.     (void) Net_UltraAddrToString(&ultraHdrPtr->remoteAddress.address, 
  2765.             address);
  2766.     printf("NetUltraOutput: sending to %s\n", address);
  2767.     }
  2768.     status = NetUltraSendReq(statePtr, OutputDone, 
  2769.         (ClientData) statusPtr, rpc, scatterGatherLength, 
  2770.         scatterGatherPtr, sizeof(Net_UltraHeader), 
  2771.         (NetUltraRequest *) ultraHdrPtr);
  2772.     if (status != SUCCESS) {
  2773.     printf("NetUltraOutput: packet not sent\n");
  2774.     }
  2775.     MASTER_UNLOCK(&interPtr->mutex);
  2776.     return status;
  2777. }
  2778.  
  2779. /*
  2780.  *----------------------------------------------------------------------
  2781.  *
  2782.  * OutputDone --
  2783.  *
  2784.  *    This routine is called by the interrupt handler when a packet
  2785.  *    sent by NetUltraOutput completes.
  2786.  *
  2787.  * Results:
  2788.  *    None.
  2789.  *
  2790.  * Side effects:
  2791.  *    The write buffer associated with the command is added to
  2792.  *     the list of free write buffers.
  2793.  *
  2794.  *----------------------------------------------------------------------
  2795.  */
  2796.  
  2797. static void
  2798. OutputDone(interPtr, infoPtr)
  2799.     Net_Interface    *interPtr;    /* Interface. */
  2800.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  2801. {
  2802.     NetUltraRequestHdr        *hdrPtr;
  2803.     NetUltraState        *statePtr;
  2804.     ReturnStatus        *statusPtr;
  2805.     ReturnStatus        status = SUCCESS;
  2806.  
  2807.     hdrPtr = &(infoPtr->xrbPtr->request.dgram.hdr);
  2808.     statusPtr = (ReturnStatus *) infoPtr->doneData;
  2809.  
  2810.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2811.     if (!(hdrPtr->status & NET_ULTRA_STATUS_OK)) {
  2812.     printf("Warning: OutputDone: write failed 0x%x\n", hdrPtr->status);
  2813.     status = FAILURE;
  2814.     } 
  2815. #ifndef CLEAN
  2816.     if (netUltraDebug) {
  2817.     printf("OutputDone: packet sent\n");
  2818.     }
  2819. #endif
  2820.     statePtr->numWritePending--;
  2821.     if (statePtr->numWritePending < 0) {
  2822.     panic("OutputDone: number of pending writes < 0.\n");
  2823.     }
  2824.     /*
  2825.      * Return status to the waiting process.
  2826.      */
  2827.     if (statusPtr != (ReturnStatus *) NIL) {
  2828.     *statusPtr = status;
  2829.     }
  2830.     /*
  2831.      * Wakeup any process waiting for the packet to be sent.
  2832.      */
  2833.     infoPtr->scatterPtr->done = TRUE;
  2834.     if (infoPtr->scatterPtr->mutexPtr != (Sync_Semaphore *) NIL) {
  2835.     NetOutputWakeup(infoPtr->scatterPtr->mutexPtr);
  2836.     }
  2837. }
  2838.  
  2839. /*
  2840.  *----------------------------------------------------------------------
  2841.  *
  2842.  * NetUltraSource --
  2843.  *
  2844.  *    This routine will send a stream of datagrams to the specified host.
  2845.  *
  2846.  * Results:
  2847.  *    None.
  2848.  *
  2849.  * Side effects:
  2850.  *    A write is queued to the adapter.
  2851.  *
  2852.  *----------------------------------------------------------------------
  2853.  */
  2854.  
  2855. static ReturnStatus
  2856. NetUltraSource(interPtr, netAddressPtr, count, bufSize, buffer, timePtr)
  2857.     Net_Interface    *interPtr;        /* Interface to send on. */
  2858.     Net_Address        *netAddressPtr;        /* Host to send to. */
  2859.     int            count;            /* Number of times to send
  2860.                          * datagram. */
  2861.     int            bufSize;        /* Size of data buffer. */
  2862.     Address        buffer;            /* Data to send. */
  2863.     Time        *timePtr;        /* Place to store total 
  2864.                          * time to send datagrams. */
  2865. {
  2866.     NetUltraState        *statePtr;
  2867.     NetUltraRequest        request;
  2868.     NetUltraDatagramRequest    *dgramReqPtr;
  2869.     NetUltraRequestHdr        *hdrPtr;
  2870.     ReturnStatus        status = SUCCESS;
  2871.     List_Links            *itemPtr;
  2872.     Timer_Ticks         startTime;
  2873.     Timer_Ticks         endTime;
  2874.     Timer_Ticks         curTime;
  2875.     NetUltraTraceInfo        *tracePtr;
  2876.     Net_ScatterGather        scatter;
  2877.     char            *ptr;
  2878.  
  2879.     MASTER_LOCK(&interPtr->mutex);
  2880. #ifndef CLEAN
  2881.     if (netUltraDebug) {
  2882.     char    address[100];
  2883.     (void) Net_AddrToString(netAddressPtr, address);
  2884.     printf("NetUltraSendDgram: sending to %s\n", address);
  2885.     }
  2886. #endif
  2887.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2888.     if (!(statePtr->flags & NET_ULTRA_STATE_START)) {
  2889.     printf("NetUltraSendDgram: adapter not started!\n");
  2890.     status = FAILURE;
  2891.     goto exit;
  2892.     }
  2893.     bzero((char *) &request, sizeof(request));
  2894.     dgramReqPtr = &request.dgram;
  2895.     hdrPtr = &dgramReqPtr->hdr;
  2896.     dgramReqPtr->remoteAddress = wildcardAddress;
  2897.     dgramReqPtr->remoteAddress.tsapSize = 2;
  2898.     dgramReqPtr->remoteAddress.tsap[1] = 1;
  2899.     dgramReqPtr->remoteAddress.address = netAddressPtr->address.ultra;
  2900.     ptr = (char *) &dgramReqPtr->remoteAddress.address;
  2901.     ptr[1] = 0x49;
  2902.     ptr[6] = 0xfe;
  2903.     dgramReqPtr->localAddress = wildcardAddress;
  2904.     dgramReqPtr->localAddress.tsapSize = 2;
  2905.     dgramReqPtr->localAddress.tsap[1] = 1;
  2906.     dgramReqPtr->localAddress.address = 
  2907.     interPtr->netAddress[NET_PROTO_RAW].address.ultra;
  2908.     ptr = (char *) &dgramReqPtr->localAddress.address;
  2909.     ptr[1] = 0x49;
  2910.     ptr[6] = 0xfe;
  2911.     hdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
  2912.     Timer_GetCurrentTicks(&startTime);
  2913.     while(count > 0) {
  2914.     count--;
  2915.     while(List_IsEmpty(statePtr->freeBufferList)) {
  2916.         int        signal;
  2917.         statePtr->bufferAvail.waiting = TRUE;
  2918.         signal = Sync_SlowMasterWait((unsigned int) &statePtr->bufferAvail,
  2919.             &interPtr->mutex, TRUE);
  2920.         if (signal) {
  2921.         status = GEN_ABORTED_BY_SIGNAL;
  2922.         goto exit;
  2923.         }
  2924.     }
  2925.     itemPtr = List_First(statePtr->freeBufferList);
  2926.     if (itemPtr == statePtr->freeBufferList) {
  2927.         panic("NetUltraSendDgram: list screwup\n");
  2928.     }
  2929.     List_Remove(itemPtr);
  2930.     if (buffer != (Address) NIL) {
  2931.         bcopy((char *) buffer, (char *) itemPtr, bufSize);
  2932.     }
  2933.     dsndCount = count;
  2934. #ifndef CLEAN
  2935.     if (netUltraTrace) {
  2936.         NEXT_TRACE(statePtr, &tracePtr);
  2937.         tracePtr->event = DSND_STREAM;
  2938.         Timer_GetCurrentTicks(&curTime);
  2939.         tracePtr->ticks = curTime;
  2940.     }
  2941. #endif
  2942.     scatter.bufAddr = BUFFER_TO_DVMA(itemPtr, statePtr);
  2943.     scatter.length = bufSize;
  2944.     status = NetUltraSendReq(statePtr, SourceDone, 
  2945.             (ClientData) NIL, FALSE, 1, &scatter,
  2946.             sizeof(NetUltraDatagramRequest), &request);
  2947.     }
  2948.     Timer_GetCurrentTicks(&endTime);
  2949.     Timer_SubtractTicks(endTime, startTime, &endTime);
  2950.     Timer_TicksToTime(endTime, timePtr);
  2951. exit:
  2952.     MASTER_UNLOCK(&interPtr->mutex);
  2953.     return status;
  2954. }
  2955.  
  2956. /*
  2957.  *----------------------------------------------------------------------
  2958.  *
  2959.  * SourceDone --
  2960.  *
  2961.  *    This routine is called by the interrupt handler when a packet
  2962.  *    sent by  NetUltraSource completes.
  2963.  *
  2964.  * Results:
  2965.  *    None.
  2966.  *
  2967.  * Side effects:
  2968.  *    The write buffer associated with the command is added to
  2969.  *     the list of free write buffers.
  2970.  *
  2971.  *----------------------------------------------------------------------
  2972.  */
  2973.  
  2974. static void
  2975. SourceDone(interPtr, infoPtr)
  2976.     Net_Interface    *interPtr;    /* Interface. */
  2977.     NetUltraXRBInfo    *infoPtr;    /* Info about XRB that completed. */
  2978. {
  2979.     NetUltraRequestHdr        *hdrPtr;
  2980.     NetUltraState        *statePtr;
  2981.     List_Links            *itemPtr;
  2982.  
  2983.     hdrPtr = &(infoPtr->xrbPtr->request.dgram.hdr);
  2984.  
  2985.     statePtr = (NetUltraState *) interPtr->interfaceData;
  2986.     if (!(hdrPtr->status & NET_ULTRA_STATUS_OK)) {
  2987.     panic("SourceDone: write failed 0x%x (continuable)\n", hdrPtr->status);
  2988.     } else {
  2989. #ifndef CLEAN
  2990.     if (netUltraDebug) {
  2991.         printf("SourceDone: packet sent\n");
  2992.     }
  2993. #endif
  2994.     statePtr->numWritePending--;
  2995.     if (statePtr->numWritePending < 0) {
  2996.         panic("SourceDone: number of pending writes < 0.\n");
  2997.     }
  2998.     /*
  2999.      * Free up the write buffer. 
  3000.      */
  3001.     itemPtr = (List_Links *) VME_TO_BUFFER(hdrPtr->buffer,statePtr);
  3002.     List_Insert(itemPtr, LIST_ATREAR(statePtr->freeBufferList));
  3003.     if (statePtr->bufferAvail.waiting == TRUE) {
  3004.         Sync_Broadcast(&statePtr->bufferAvail);
  3005.     }
  3006.     }
  3007. }
  3008.  
  3009. /*
  3010.  *----------------------------------------------------------------------
  3011.  *
  3012.  * NetUltraGetStats --
  3013.  *
  3014.  *    Return the statistics for the interface.
  3015.  *
  3016.  * Results:
  3017.  *    A pointer to the statistics structure.
  3018.  *
  3019.  * Side effects:
  3020.  *    None.
  3021.  *
  3022.  *----------------------------------------------------------------------
  3023.  */
  3024.  
  3025. ReturnStatus
  3026. NetUltraGetStats(interPtr, statPtr)
  3027.     Net_Interface    *interPtr;        /* Current interface. */
  3028.     Net_Stats        *statPtr;        /* Statistics to return. */
  3029. {
  3030.     NetUltraState    *statePtr;
  3031.  
  3032.     statePtr = (NetUltraState *) interPtr->interfaceData;
  3033.     MASTER_LOCK(&interPtr->mutex);
  3034.     statPtr->ultra = statePtr->stats;
  3035.     MASTER_UNLOCK(&interPtr->mutex);
  3036.     return SUCCESS;
  3037. }
  3038.  
  3039.